LatinIME.java revision 32f0af1fc48f67907f0e731e18359f29e2b1df14
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; 528d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanvimport com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; 53c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.CompatUtils; 54c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.EditorInfoCompatUtils; 55c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputConnectionCompatUtils; 56c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputMethodManagerCompatWrapper; 57c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputMethodServiceCompatWrapper; 58c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputTypeCompatUtils; 591fef530ec7626fa16777f52b48191e61db8f46d4satokimport com.android.inputmethod.compat.SuggestionSpanUtils; 6028f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasaimport com.android.inputmethod.compat.VibratorCompatWrapper; 61c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.deprecated.LanguageSwitcherProxy; 62c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.deprecated.VoiceProxy; 63c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.Keyboard; 64c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardActionListener; 656b7100fecaaaf0e8e42c4d2ccebac165e89e79bfTadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardId; 66c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardSwitcher; 67f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardView; 68c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaokaimport com.android.inputmethod.keyboard.LatinKeyboardView; 698c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaokaimport com.android.inputmethod.latin.suggestions.SuggestionsView; 70923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 71466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.FileDescriptor; 72466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.PrintWriter; 73466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.Locale; 74466741d8a78965b8509bf527344f289e50873092Mike LeBeau 75923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/** 76923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Input method implementation for Qwerty'ish keyboard. 77923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 78c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaokapublic class LatinIME extends InputMethodServiceCompatWrapper implements KeyboardActionListener, 79913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka SuggestionsView.Listener { 808efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka private static final String TAG = LatinIME.class.getSimpleName(); 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. 1101ef6fc7e1519cedec9e84a64968bfba4212d0436Tadashi G. Takaoka * 1111ef6fc7e1519cedec9e84a64968bfba4212d0436Tadashi G. Takaoka * @deprecated Use {@link EditorInfo#IME_FLAG_FORCE_ASCII}. 112af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka */ 1131ef6fc7e1519cedec9e84a64968bfba4212d0436Tadashi G. Takaoka @SuppressWarnings("dep-ann") 114af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka public static final String IME_OPTION_FORCE_ASCII = "forceAscii"; 115af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka 116af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka /** 117af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka * The subtype extra value used to indicate that the subtype keyboard layout is capable for 118af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka * typing ASCII characters. 119af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka */ 120af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka public static final String SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable"; 121af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka 122d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka /** 123294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima * The subtype extra value used to indicate that the subtype keyboard layout supports touch 124294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima * position correction. 125294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima */ 126294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima public static final String SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION = 127294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima "SupportTouchPositionCorrection"; 128294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima /** 129d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka * The subtype extra value used to indicate that the subtype keyboard layout should be loaded 130d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka * from the specified locale. 131d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka */ 132d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka public static final String SUBTYPE_EXTRA_VALUE_KEYBOARD_LOCALE = "KeyboardLocale"; 133d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka 1349e347d3d448e48229c46aad394ec9bd60cd5807bsatok private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100; 135fd0bd57deb53c4cce32810a61133fa44b45dbb7bKen Wakasa 136923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // How many continuous deletes at which to start deleting at a higher speed. 137923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int DELETE_ACCELERATE_AT = 20; 138923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Key events coming any faster than this are long-presses. 139d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani private static final int QUICK_PRESS = 200; 140a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 14159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private static final int PENDING_IMS_CALLBACK_DURATION = 800; 142055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 143cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard /** 144cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard * The name of the scheme used by the Package Manager to warn of a new package installation, 145cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard * replacement or removal. 146cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard */ 147cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard private static final String SCHEME_PACKAGE = "package"; 148cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 1490fe3611bee5095e7bd0fff2d0fdf8d5a13379132Jean Chalard // TODO: migrate this to SettingsValues 1507599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private int mSuggestionVisibility; 1517599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_VALUE 1527599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_value; 1537599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 1547599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_only_portrait_value; 1557599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_HIDE_VALUE 1567599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_hide_value; 1577599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 1587599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int[] SUGGESTION_VISIBILITY_VALUE_ARRAY = new int[] { 1597599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_VALUE, 1607599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE, 1617599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_HIDE_VALUE 1627599cfea4a2d56f4779452ec8e8742f7b9629cc0satok }; 1637599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 164fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard private static final int SPACE_STATE_NONE = 0; 165120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Double space: the state where the user pressed space twice quickly, which LatinIME 166120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // resolved as period-space. Undoing this converts the period to a space. 167fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard private static final int SPACE_STATE_DOUBLE = 1; 168b141c9cd3f6785bc0a4e1f5385f4e6e2e17955bbJean Chalard // Swap punctuation: the state where a weak space and a punctuation from the suggestion strip 169b141c9cd3f6785bc0a4e1f5385f4e6e2e17955bbJean Chalard // have just been swapped. Undoing this swaps them back; the space is still considered weak. 170120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private static final int SPACE_STATE_SWAP_PUNCTUATION = 2; 171fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // Weak space: a space that should be swapped only by suggestion strip punctuation. Weak 172fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // spaces happen when the user presses space, accepting the current suggestion (whether 173fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // it's an auto-correction or not). 174fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard private static final int SPACE_STATE_WEAK = 3; 175fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // Phantom space: a not-yet-inserted space that should get inserted on the next input, 176fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // character provided it's not a separator. If it's a separator, the phantom space is dropped. 177fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // Phantom spaces happen when a user chooses a word from the suggestion strip. 178fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard private static final int SPACE_STATE_PHANTOM = 4; 179120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 180120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Current space state of the input method. This can be any of the above constants. 181120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private int mSpaceState; 182126698fdd256a2e3734634d3b923cabd800064baJean Chalard 1837a16a061e622539e54d7d649dcb8d4965aea575aJean Chalard private SettingsValues mSettingsValues; 18480b66bb166f7f45adfcadcb84788477df9930828Jean Chalard private InputAttributes mInputAttributes; 18517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 186d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka private View mExtractArea; 187abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka private View mKeyPreviewBackingView; 188913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka private View mSuggestionsContainer; 189913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka private SuggestionsView mSuggestionsView; 190816a8a0fd85ca0327436f8bd1cfa6928600ebc5dJean Chalard /* package for tests */ Suggest mSuggest; 1911b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka private CompletionInfo[] mApplicationSpecifiedCompletions; 192a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 193610f1dc8553cf2ed97e763a06a19380c4a6cd636satok private InputMethodManagerCompatWrapper mImm; 1942fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private Resources mResources; 1952fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private SharedPreferences mPrefs; 19671c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka private KeyboardSwitcher mKeyboardSwitcher; 1970ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private SubtypeSwitcher mSubtypeSwitcher; 198b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok private VoiceProxy mVoiceProxy; 199a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 200923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private UserDictionary mUserDictionary; 201979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private UserBigramDictionary mUserBigramDictionary; 202f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard private UserUnigramDictionary mUserUnigramDictionary; 20388562bec54658840dcce352127bdc15705c20a89Jean Chalard private boolean mIsUserDictionaryAvailable; 20436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 2052692a8700737d8eed268039aa27b22a31669da08Jean Chalard private LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; 2069318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa private WordComposer mWordComposer = new WordComposer(); 207409220583333bdf06290dd9fd42f91b5c0d1b11asatok 20879efbed76f638be298493107fa2d0cd1b5eb529esatok private int mCorrectionMode; 20977da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard 210979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Keep track of the last selection range to decide if we need to show word alternatives 21177da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard private static final int NOT_A_CURSOR_POSITION = -1; 21277da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard private int mLastSelectionStart = NOT_A_CURSOR_POSITION; 21377da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard private int mLastSelectionEnd = NOT_A_CURSOR_POSITION; 214979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2154733609947c0ec74e460bd714fffca0518ade93aJean Chalard // Whether we are expecting an onUpdateSelection event to fire. If it does when we don't 2164733609947c0ec74e460bd714fffca0518ade93aJean Chalard // "expect" it, it means the user actually moved the cursor. 2174733609947c0ec74e460bd714fffca0518ade93aJean Chalard private boolean mExpectingUpdateSelection; 218923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mDeleteCount; 219923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastKeyTime; 220a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 221923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private AudioManager mAudioManager; 22217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard private boolean mSilentModeOn; // System-wide current configuration 223923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 22428f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa private VibratorCompatWrapper mVibrator; 22528f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa 226b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok // TODO: Move this flag to VoiceProxy 22781c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani private boolean mConfigurationChanging; 228466741d8a78965b8509bf527344f289e50873092Mike LeBeau 22938f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka // Member variables for remembering the current device orientation. 23038f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka private int mDisplayOrientation; 23138f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 232cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Object for reacting to adding/removing a dictionary pack. 233cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard private BroadcastReceiver mDictionaryPackInstallReceiver = 234cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard new DictionaryPackInstallBroadcastReceiver(this); 235cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 236dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Keeps track of most recently inserted text (multi-character key) for reverting 237dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani private CharSequence mEnteredText; 238dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 239604d80c67185954d4691ac775be59c499eee3b1csatok private final ComposingStateManager mComposingStateManager = 240fe2d90798ea409ee39d6f63942eb01bb7eed98e3satok ComposingStateManager.getInstance(); 241604d80c67185954d4691ac775be59c499eee3b1csatok 2424f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public final UIHandler mHandler = new UIHandler(this); 243d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 2444f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public static class UIHandler extends StaticInnerHandlerWrapper<LatinIME> { 245d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_SUGGESTIONS = 0; 24645f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_UPDATE_SHIFT_STATE = 1; 24745f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_VOICE_RESULTS = 2; 24845f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 3; 24945f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 4; 25045f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_SPACE_TYPED = 5; 25193246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka private static final int MSG_SET_BIGRAM_PREDICTIONS = 6; 25293246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka private static final int MSG_PENDING_IMS_CALLBACK = 7; 253175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka 25410dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private int mDelayBeforeFadeoutLanguageOnSpacebar; 25510dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private int mDelayUpdateSuggestions; 25610dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private int mDelayUpdateShiftState; 25710dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private int mDurationOfFadeoutLanguageOnSpacebar; 25810dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private float mFinalFadeoutFactorOfLanguageOnSpacebar; 25910dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private long mDoubleSpacesTurnIntoPeriodTimeout; 26038f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 2614f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public UIHandler(LatinIME outerInstance) { 2624f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa super(outerInstance); 26310dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka } 264175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka 26510dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka public void onCreate() { 26610dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka final Resources res = getOuterInstance().getResources(); 267175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDelayBeforeFadeoutLanguageOnSpacebar = res.getInteger( 268175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka R.integer.config_delay_before_fadeout_language_on_spacebar); 269175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDelayUpdateSuggestions = 270175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka res.getInteger(R.integer.config_delay_update_suggestions); 271175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDelayUpdateShiftState = 272175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka res.getInteger(R.integer.config_delay_update_shift_state); 273175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDurationOfFadeoutLanguageOnSpacebar = res.getInteger( 274175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka R.integer.config_duration_of_fadeout_language_on_spacebar); 275175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mFinalFadeoutFactorOfLanguageOnSpacebar = res.getInteger( 276175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka R.integer.config_final_fadeout_percentage_of_language_on_spacebar) / 100.0f; 277175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDoubleSpacesTurnIntoPeriodTimeout = res.getInteger( 278175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka R.integer.config_double_spaces_turn_into_period_timeout); 2794f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa } 2804f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa 281923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 282923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void handleMessage(Message msg) { 2834f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final LatinIME latinIme = getOuterInstance(); 2844f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final KeyboardSwitcher switcher = latinIme.mKeyboardSwitcher; 285c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka final LatinKeyboardView inputView = switcher.getKeyboardView(); 286923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (msg.what) { 287d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SUGGESTIONS: 2884f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.updateSuggestions(); 289d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 290d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SHIFT_STATE: 291de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka switcher.updateShiftState(); 292d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 293cb3320179d39a7983874697a0aa428b127675c9dJean Chalard case MSG_SET_BIGRAM_PREDICTIONS: 2944f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.updateBigramPredictions(); 29589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard break; 296d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_VOICE_RESULTS: 297433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka final Keyboard keyboard = switcher.getKeyboard(); 2984f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mVoiceProxy.handleVoiceResults(latinIme.preferCapitalization() 299433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka || (keyboard != null && keyboard.isShiftedOrShiftLocked())); 300de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka break; 301de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka case MSG_FADEOUT_LANGUAGE_ON_SPACEBAR: 30223d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka setSpacebarTextFadeFactor(inputView, 30323d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka (1.0f + mFinalFadeoutFactorOfLanguageOnSpacebar) / 2, 3043708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka (Keyboard)msg.obj); 305de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_DISMISS_LANGUAGE_ON_SPACEBAR, msg.obj), 306175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDurationOfFadeoutLanguageOnSpacebar); 307de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka break; 308de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka case MSG_DISMISS_LANGUAGE_ON_SPACEBAR: 30923d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka setSpacebarTextFadeFactor(inputView, mFinalFadeoutFactorOfLanguageOnSpacebar, 3103708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka (Keyboard)msg.obj); 311d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 312923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 313923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 314d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 315d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateSuggestions() { 316d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 317175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS), mDelayUpdateSuggestions); 318d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 319d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 320d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateSuggestions() { 321d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 322d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 323d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 324d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public boolean hasPendingUpdateSuggestions() { 325d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka return hasMessages(MSG_UPDATE_SUGGESTIONS); 326d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 327d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 328beb08b398fa73a26f2d42d6feec87e34a96ca2d9Tadashi G. Takaoka public void postUpdateShiftState() { 329d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 330175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE), mDelayUpdateShiftState); 331d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 332d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 333d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateShiftState() { 334d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 335d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 336d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 337cb3320179d39a7983874697a0aa428b127675c9dJean Chalard public void postUpdateBigramPredictions() { 338cb3320179d39a7983874697a0aa428b127675c9dJean Chalard removeMessages(MSG_SET_BIGRAM_PREDICTIONS); 339175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS), mDelayUpdateSuggestions); 34089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 34189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 342cb3320179d39a7983874697a0aa428b127675c9dJean Chalard public void cancelUpdateBigramPredictions() { 343cb3320179d39a7983874697a0aa428b127675c9dJean Chalard removeMessages(MSG_SET_BIGRAM_PREDICTIONS); 34489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 34589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 346d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void updateVoiceResults() { 347d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessage(obtainMessage(MSG_VOICE_RESULTS)); 348d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 349de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka 35023d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka private static void setSpacebarTextFadeFactor(LatinKeyboardView inputView, 3513708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka float fadeFactor, Keyboard oldKeyboard) { 35223d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka if (inputView == null) return; 35323d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka final Keyboard keyboard = inputView.getKeyboard(); 3543708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka if (keyboard == oldKeyboard) { 3554112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka inputView.updateSpacebar(fadeFactor, 3564112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka SubtypeSwitcher.getInstance().needsToDisplayLanguage( 3574112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka keyboard.mId.mLocale)); 35823d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka } 35923d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka } 36023d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka 361d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka public void startDisplayLanguageOnSpacebar(boolean localeChanged) { 3624f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final LatinIME latinIme = getOuterInstance(); 363de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka removeMessages(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR); 364de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka removeMessages(MSG_DISMISS_LANGUAGE_ON_SPACEBAR); 365c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka final LatinKeyboardView inputView = latinIme.mKeyboardSwitcher.getKeyboardView(); 366de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka if (inputView != null) { 3673708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka final Keyboard keyboard = latinIme.mKeyboardSwitcher.getKeyboard(); 368c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka // The language is always displayed when the delay is negative. 369c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka final boolean needsToDisplayLanguage = localeChanged 370175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka || mDelayBeforeFadeoutLanguageOnSpacebar < 0; 371de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka // The language is never displayed when the delay is zero. 372175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka if (mDelayBeforeFadeoutLanguageOnSpacebar != 0) { 37323d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka setSpacebarTextFadeFactor(inputView, 37423d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka needsToDisplayLanguage ? 1.0f : mFinalFadeoutFactorOfLanguageOnSpacebar, 37523d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka keyboard); 37617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 377c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka // The fadeout animation will start when the delay is positive. 378175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka if (localeChanged && mDelayBeforeFadeoutLanguageOnSpacebar > 0) { 379de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR, keyboard), 380175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDelayBeforeFadeoutLanguageOnSpacebar); 381de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 382de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 383de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 384fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 385fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public void startDoubleSpacesTimer() { 386fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka removeMessages(MSG_SPACE_TYPED); 387175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED), mDoubleSpacesTurnIntoPeriodTimeout); 388fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 389fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 390fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public void cancelDoubleSpacesTimer() { 391fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka removeMessages(MSG_SPACE_TYPED); 392fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 393fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 394fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public boolean isAcceptingDoubleSpaces() { 395fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka return hasMessages(MSG_SPACE_TYPED); 396fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 39738f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 39859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Working variables for the following methods. 39959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mIsOrientationChanging; 4005fd11a7f3367d51cea8dc83fb9675c93d82a2e4eJean Chalard private boolean mPendingSuccessiveImsCallback; 40159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mHasPendingStartInput; 40259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mHasPendingFinishInputView; 40359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mHasPendingFinishInput; 404e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka private EditorInfo mAppliedEditorInfo; 40559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 40659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void startOrientationChanging() { 407dd25e4fa2c7dd1e32a9e6f5fd21f54214919ef20Tadashi G. Takaoka removeMessages(MSG_PENDING_IMS_CALLBACK); 408dd25e4fa2c7dd1e32a9e6f5fd21f54214919ef20Tadashi G. Takaoka resetPendingImsCallback(); 40959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mIsOrientationChanging = true; 410055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 411f2c9a88887a303f3df8bee60788870946dfa55f7Tadashi G. Takaoka if (latinIme.isInputViewShown()) { 412f2c9a88887a303f3df8bee60788870946dfa55f7Tadashi G. Takaoka latinIme.mKeyboardSwitcher.saveKeyboardState(); 413f2c9a88887a303f3df8bee60788870946dfa55f7Tadashi G. Takaoka } 41459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 41559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 41659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void resetPendingImsCallback() { 41759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInputView = false; 41859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInput = false; 41959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingStartInput = false; 42059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 42159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 422e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka private void executePendingImsCallback(LatinIME latinIme, EditorInfo editorInfo, 42359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka boolean restarting) { 42459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mHasPendingFinishInputView) 42559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputViewInternal(mHasPendingFinishInput); 42659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mHasPendingFinishInput) 42759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputInternal(); 42859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mHasPendingStartInput) 429e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka latinIme.onStartInputInternal(editorInfo, restarting); 43059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka resetPendingImsCallback(); 43159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 43259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 433e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka public void onStartInput(EditorInfo editorInfo, boolean restarting) { 43459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { 43559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Typically this is the second onStartInput after orientation changed. 43659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingStartInput = true; 43759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } else { 43859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mIsOrientationChanging && restarting) { 43959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // This is the first onStartInput after orientation changed. 44059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mIsOrientationChanging = false; 4415fd11a7f3367d51cea8dc83fb9675c93d82a2e4eJean Chalard mPendingSuccessiveImsCallback = true; 44259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 44359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 444e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka executePendingImsCallback(latinIme, editorInfo, restarting); 445e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka latinIme.onStartInputInternal(editorInfo, restarting); 446055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 447055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 448055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 449e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka public void onStartInputView(EditorInfo editorInfo, boolean restarting) { 4506b7100fecaaaf0e8e42c4d2ccebac165e89e79bfTadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK) 4516b7100fecaaaf0e8e42c4d2ccebac165e89e79bfTadashi G. Takaoka && KeyboardId.equivalentEditorInfoForKeyboard(editorInfo, mAppliedEditorInfo)) { 452e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka // Typically this is the second onStartInputView after orientation changed. 453e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka resetPendingImsCallback(); 454e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka } else { 4555fd11a7f3367d51cea8dc83fb9675c93d82a2e4eJean Chalard if (mPendingSuccessiveImsCallback) { 456e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka // This is the first onStartInputView after orientation changed. 4575fd11a7f3367d51cea8dc83fb9675c93d82a2e4eJean Chalard mPendingSuccessiveImsCallback = false; 458e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka resetPendingImsCallback(); 459e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_PENDING_IMS_CALLBACK), 460e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka PENDING_IMS_CALLBACK_DURATION); 461e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka } 462e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 463e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka executePendingImsCallback(latinIme, editorInfo, restarting); 464e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka latinIme.onStartInputViewInternal(editorInfo, restarting); 465e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mAppliedEditorInfo = editorInfo; 466e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka } 46759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 46859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 46959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInputView(boolean finishingInput) { 47059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { 47159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Typically this is the first onFinishInputView after orientation changed. 47259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInputView = true; 47359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } else { 47459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 47559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputViewInternal(finishingInput); 476e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mAppliedEditorInfo = null; 47738f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 47838f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 479ffd156c77e93a54b704780b46886ba597d1c77cbTadashi G. Takaoka 48059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInput() { 48159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { 48259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Typically this is the first onFinishInput after orientation changed. 48359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInput = true; 48459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } else { 48559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 48659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka executePendingImsCallback(latinIme, null, false); 48759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputInternal(); 488ffd156c77e93a54b704780b46886ba597d1c77cbTadashi G. Takaoka } 489ffd156c77e93a54b704780b46886ba597d1c77cbTadashi G. Takaoka } 49038f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 49138f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 4927e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 4937e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka public void onCreate() { 49427d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 49527d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mPrefs = prefs; 49627d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa LatinImeLogger.init(this, prefs); 4976d9021527a38ba1e94225020389621a0d7227aa1satok LanguageSwitcherProxy.init(this, prefs); 498bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka InputMethodManagerCompatWrapper.init(this); 499ef5dfc480c7a3e3e34a20b7aacc731942e7a0578Tadashi G. Takaoka SubtypeSwitcher.init(this); 50027d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa KeyboardSwitcher.init(this, prefs); 5012ac5988f84b5c38d313951a3d7faddebf5f25e04Tadashi G. Takaoka AccessibilityUtils.init(this); 502363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 503923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onCreate(); 504363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 505bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka mImm = InputMethodManagerCompatWrapper.getInstance(); 5060ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 5070ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mKeyboardSwitcher = KeyboardSwitcher.getInstance(); 50828f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa mVibrator = VibratorCompatWrapper.getInstance(this); 50910dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka mHandler.onCreate(); 5109e2d810dc524380ca1db6b384cfb00b4401585e5Tadashi G. Takaoka DEBUG = LatinImeLogger.sDBG; 511363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 512363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka final Resources res = getResources(); 513363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka mResources = res; 514fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard 51528f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa loadSettings(); 51628f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa 517dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard // TODO: remove the following when it's not needed by updateCorrectionMode() any more 518644c8b7c96627199c13297082e4566adae159bf3Jean Chalard mInputAttributes = new InputAttributes(null, false /* isFullscreenMode */); 5199502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Utils.GCUtils.getInstance().reset(); 520979f8690967ff5409fe18f5085858ccdb8e0ccf1satok boolean tryGC = true; 5219502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { 522979f8690967ff5409fe18f5085858ccdb8e0ccf1satok try { 5230ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 524979f8690967ff5409fe18f5085858ccdb8e0ccf1satok tryGC = false; 525979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } catch (OutOfMemoryError e) { 5269502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka tryGC = Utils.GCUtils.getInstance().tryGCOrWait("InitSuggest", e); 527979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 528979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 529979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 530f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka mDisplayOrientation = res.getConfiguration().orientation; 531b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 532cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Register to receive ringer mode change and network state change. 533cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Also receive installation and removal of a dictionary pack. 534123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final IntentFilter filter = new IntentFilter(); 535123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); 536123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 537923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project registerReceiver(mReceiver, filter); 538b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy = VoiceProxy.init(this, prefs, mHandler); 539cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 540cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final IntentFilter packageFilter = new IntentFilter(); 541cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 542cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 543cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addDataScheme(SCHEME_PACKAGE); 544cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard registerReceiver(mDictionaryPackInstallReceiver, packageFilter); 545646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard 546646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard final IntentFilter newDictFilter = new IntentFilter(); 547646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard newDictFilter.addAction( 548646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard DictionaryPackInstallBroadcastReceiver.NEW_DICTIONARY_INTENT_ACTION); 549646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard registerReceiver(mDictionaryPackInstallReceiver, newDictFilter); 550923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 55136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 55217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // Has to be package-visible for unit tests 55317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard /* package */ void loadSettings() { 55417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this); 55517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (null == mSubtypeSwitcher) mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 5567a16a061e622539e54d7d649dcb8d4965aea575aJean Chalard mSettingsValues = new SettingsValues(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr()); 55714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary()); 55817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 55917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 5600ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private void initSuggest() { 561cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); 562ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr); 56336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 564309bff562fbaf47488e6bf6636840f00574187d8Jean Chalard final Resources res = mResources; 565ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard final Locale savedLocale = LocaleUtils.setSystemLocale(res, keyboardLocale); 56614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard final ContactsDictionary oldContactsDictionary; 56736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani if (mSuggest != null) { 56814051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard oldContactsDictionary = mSuggest.getContactsDictionary(); 56936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mSuggest.close(); 57014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } else { 57114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard oldContactsDictionary = null; 57236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 573979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 5748efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka int mainDicResId = Utils.getMainDictionaryResourceId(res); 575cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mSuggest = new Suggest(this, mainDicResId, keyboardLocale); 57617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.mAutoCorrectEnabled) { 57717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); 57817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 579e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 580cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mUserDictionary = new UserDictionary(this, localeStr); 581923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mSuggest.setUserDictionary(mUserDictionary); 58288562bec54658840dcce352127bdc15705c20a89Jean Chalard mIsUserDictionaryAvailable = mUserDictionary.isEnabled(); 583e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 58414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard resetContactsDictionary(oldContactsDictionary); 585e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 586f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard mUserUnigramDictionary 587f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard = new UserUnigramDictionary(this, this, localeStr, Suggest.DIC_USER_UNIGRAM); 588f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard mSuggest.setUserUnigramDictionary(mUserUnigramDictionary); 589e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 590f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard mUserBigramDictionary 591f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard = new UserBigramDictionary(this, this, localeStr, Suggest.DIC_USER_BIGRAM); 592e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.setUserBigramDictionary(mUserBigramDictionary); 593e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 594e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani updateCorrectionMode(); 59536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 596ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard LocaleUtils.setSystemLocale(res, savedLocale); 597923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 59836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 59914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard /** 60014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * Resets the contacts dictionary in mSuggest according to the user settings. 60114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * 60214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * This method takes an optional contacts dictionary to use. Since the contacts dictionary 60314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * does not depend on the locale, it can be reused across different instances of Suggest. 60414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * The dictionary will also be opened or closed as necessary depending on the settings. 60514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * 60614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * @param oldContactsDictionary an optional dictionary to use, or null 60714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard */ 60814051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard private void resetContactsDictionary(final ContactsDictionary oldContactsDictionary) { 60914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard final boolean shouldSetDictionary = (null != mSuggest && mSettingsValues.mUseContactsDict); 61014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard 61114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard final ContactsDictionary dictionaryToUse; 61214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (!shouldSetDictionary) { 61314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // Make sure the dictionary is closed. If it is already closed, this is a no-op, 61414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // so it's safe to call it anyways. 61514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (null != oldContactsDictionary) oldContactsDictionary.close(); 61614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard dictionaryToUse = null; 61714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } else if (null != oldContactsDictionary) { 61814051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // Make sure the old contacts dictionary is opened. If it is already open, this is a 61914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // no-op, so it's safe to call it anyways. 62014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard oldContactsDictionary.reopen(this); 62114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard dictionaryToUse = oldContactsDictionary; 62214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } else { 62314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard dictionaryToUse = new ContactsDictionary(this, Suggest.DIC_CONTACTS); 62414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } 62514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard 62614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (null != mSuggest) { 62714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard mSuggest.setContactsDictionary(dictionaryToUse); 62814051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } 629699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard } 630699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard 631cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard /* package private */ void resetSuggestMainDict() { 632cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); 633ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr); 634cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard int mainDicResId = Utils.getMainDictionaryResourceId(mResources); 635cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mSuggest.resetMainDict(this, mainDicResId, keyboardLocale); 636cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard } 637cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 638466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 639466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onDestroy() { 640e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa if (mSuggest != null) { 641e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.close(); 642e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest = null; 643979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 644923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project unregisterReceiver(mReceiver); 645cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard unregisterReceiver(mDictionaryPackInstallReceiver); 646b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.destroy(); 647979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 648979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.onDestroy(); 649923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onDestroy(); 650923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 651923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 652923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 653923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onConfigurationChanged(Configuration conf) { 654dc64b138b5e3fb3706c0818d0a308fe6e36985b0Tadashi G. Takaoka mSubtypeSwitcher.onConfigurationChanged(conf); 655604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.onFinishComposingText(); 656b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani // If orientation changed while predicting, commit the change 657f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka if (mDisplayOrientation != conf.orientation) { 658f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka mDisplayOrientation = conf.orientation; 659f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka mHandler.startOrientationChanging(); 6609351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 66166bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitTyped(ic, LastComposedWord.NOT_A_SEPARATOR); 662466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (ic != null) ic.finishComposingText(); // For voice input 6632fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka if (isShowingOptionDialog()) 6642fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka mOptionsDialog.dismiss(); 665b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 6668b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 66781c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani mConfigurationChanging = true; 668923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onConfigurationChanged(conf); 669b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.onConfigurationChanged(conf); 67081c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani mConfigurationChanging = false; 67188fc9d44186120f9edc5cf7ec0e2af85260fed04satok 67288fc9d44186120f9edc5cf7ec0e2af85260fed04satok // This will work only when the subtype is not supported. 67388fc9d44186120f9edc5cf7ec0e2af85260fed04satok LanguageSwitcherProxy.onConfigurationChanged(conf); 674923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 675b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 676923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 677923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public View onCreateInputView() { 6786c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka return mKeyboardSwitcher.onCreateInputView(); 6796c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka } 6806c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka 6816c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka @Override 6826c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka public void setInputView(View view) { 6836c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka super.setInputView(view); 684d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka mExtractArea = getWindow().getWindow().getDecorView() 685d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka .findViewById(android.R.id.extractArea); 686abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka mKeyPreviewBackingView = view.findViewById(R.id.key_preview_backing); 687913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsContainer = view.findViewById(R.id.suggestions_container); 688913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView = (SuggestionsView) view.findViewById(R.id.suggestions_view); 689913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) 690913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.setListener(this, view); 691f5fe245df0548ea0a8ec607f2392de0fe02c141dTadashi G. Takaoka if (LatinImeLogger.sVISUALDEBUG) { 692f5fe245df0548ea0a8ec607f2392de0fe02c141dTadashi G. Takaoka mKeyPreviewBackingView.setBackgroundColor(0x10FF0000); 693f5fe245df0548ea0a8ec607f2392de0fe02c141dTadashi G. Takaoka } 694923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 695923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 696923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 697c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka public void setCandidatesView(View view) { 698c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka // To ensure that CandidatesView will never be set. 699c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return; 700923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 701923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 702a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker @Override 703e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka public void onStartInput(EditorInfo editorInfo, boolean restarting) { 704e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mHandler.onStartInput(editorInfo, restarting); 70559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 70659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 70759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka @Override 708e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka public void onStartInputView(EditorInfo editorInfo, boolean restarting) { 709e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mHandler.onStartInputView(editorInfo, restarting); 71059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 71159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 71259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka @Override 71359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInputView(boolean finishingInput) { 71459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHandler.onFinishInputView(finishingInput); 71559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 71638f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 71759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka @Override 71859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInput() { 71959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHandler.onFinishInput(); 72059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 72159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 722e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka private void onStartInputInternal(EditorInfo editorInfo, boolean restarting) { 723e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka super.onStartInput(editorInfo, restarting); 72459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 72559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 726e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka private void onStartInputViewInternal(EditorInfo editorInfo, boolean restarting) { 727e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka super.onStartInputView(editorInfo, restarting); 72845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 729c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka LatinKeyboardView inputView = switcher.getKeyboardView(); 7308e09172df1bb176cc899940862c56bed9b9aec4esatok 73189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (DEBUG) { 732e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka Log.d(TAG, "onStartInputView: editorInfo:" + ((editorInfo == null) ? "none" 733f0f726464dcb5b3cef4f8e703659b35ca62430b5Tadashi G. Takaoka : String.format("inputType=0x%08x imeOptions=0x%08x", 734e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka editorInfo.inputType, editorInfo.imeOptions))); 735910b73127fa207dd26ec8124000262523b0aac0csatok } 7364f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka if (Utils.inPrivateImeOptions(null, IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo)) { 7374f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka Log.w(TAG, "Deprecated private IME option specified: " 7384f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka + editorInfo.privateImeOptions); 7394f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka Log.w(TAG, "Use " + getPackageName() + "." + IME_OPTION_NO_MICROPHONE + " instead"); 7404f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka } 7414f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka if (Utils.inPrivateImeOptions(getPackageName(), IME_OPTION_FORCE_ASCII, editorInfo)) { 7424f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka Log.w(TAG, "Deprecated private IME option specified: " 7434f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka + editorInfo.privateImeOptions); 7444f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka Log.w(TAG, "Use EditorInfo.IME_FLAG_FORCE_ASCII flag instead"); 7454f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka } 7464f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka 7477ef235f53f2291f22ddf8c56be9860a218b25bbbTadashi G. Takaoka LatinImeLogger.onStartInputView(editorInfo); 748923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In landscape mode, this method gets called without the input view being created. 749979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (inputView == null) { 750923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 751923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 752923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 753b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette // Forward this event to the accessibility utilities, if enabled. 754b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette final AccessibilityUtils accessUtils = AccessibilityUtils.getInstance(); 755b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette if (accessUtils.isTouchExplorationEnabled()) { 756e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka accessUtils.onStartInputViewInternal(editorInfo, restarting); 757b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette } 758b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette 7598d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka mSubtypeSwitcher.updateParametersOnStartInputView(); 7604ab730dbd34fad323063f2ffd31ce33de746668dsatok 761055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka // Most such things we decide below in initializeInputAttributesAndGetMode, but we need to 762055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka // know now whether this is a password text field, because we need to know now whether we 763055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka // want to enable the voice button. 764e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka final int inputType = (editorInfo != null) ? editorInfo.inputType : 0; 765104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard mVoiceProxy.resetVoiceStates(InputTypeCompatUtils.isPasswordInputType(inputType) 7663be0039164f5e2060b83d0699e293ffc76384732Tadashi G. Takaoka || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)); 767c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 768b2b1eb5ca5a52648eea70920b9bd745b07d3ddfaTadashi G. Takaoka // The EditorInfo might have a flag that affects fullscreen mode. 769b2b1eb5ca5a52648eea70920b9bd745b07d3ddfaTadashi G. Takaoka // Note: This call should be done by InputMethodService? 770b2b1eb5ca5a52648eea70920b9bd745b07d3ddfaTadashi G. Takaoka updateFullscreenMode(); 7711fead1d5f12928f90c723b5f7b88490cc7cd2a67Jean Chalard mLastSelectionStart = editorInfo.initialSelStart; 7721fead1d5f12928f90c723b5f7b88490cc7cd2a67Jean Chalard mLastSelectionEnd = editorInfo.initialSelEnd; 77380b66bb166f7f45adfcadcb84788477df9930828Jean Chalard mInputAttributes = new InputAttributes(editorInfo, isFullscreenMode()); 774ccc35f7fa74860a8d737a4e9ff01fc0168dd329dJean Chalard mApplicationSpecifiedCompletions = null; 775c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 776c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.closing(); 777c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mEnteredText = null; 7782692a8700737d8eed268039aa27b22a31669da08Jean Chalard resetComposingState(true /* alsoResetLastComposedWord */); 779c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mDeleteCount = 0; 780120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 781c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 78217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 78317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard updateCorrectionMode(); 7842ac5988f84b5c38d313951a3d7faddebf5f25e04Tadashi G. Takaoka updateSuggestionVisibility(mResources); 78517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 78617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSuggest != null && mSettingsValues.mAutoCorrectEnabled) { 78717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); 788549e295dc113bff50077c3c355dcd94af09a1b2fTadashi G. Takaoka } 789e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mVoiceProxy.loadSettings(editorInfo, mPrefs); 79017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // This will work only when the subtype is not supported. 79117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard LanguageSwitcherProxy.loadSettings(); 79217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 793c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (mSubtypeSwitcher.isKeyboardMode()) { 794e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka switcher.loadKeyboard(editorInfo, mSettingsValues); 795c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 796c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 797913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) 798913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.clear(); 799913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShownInternal( 800913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka isSuggestionsStripVisible(), /* needsInputViewShown */ false); 801c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // Delay updating suggestions because keyboard input view may not be shown at this point. 802c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mHandler.postUpdateSuggestions(); 803ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa mHandler.cancelDoubleSpacesTimer(); 804c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 805240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard inputView.setKeyPreviewPopupEnabled(mSettingsValues.mKeyPreviewPopupOn, 806240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard mSettingsValues.mKeyPreviewPopupDismissDelay); 807c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.setProximityCorrectionEnabled(true); 808c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 809104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard mVoiceProxy.onStartInputView(inputView.getWindowToken()); 810c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 811c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); 812c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 813c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 814923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 815e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka public void onWindowHidden() { 816e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka super.onWindowHidden(); 817f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 818e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka if (inputView != null) inputView.closing(); 819e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka } 820e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka 82159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void onFinishInputInternal() { 822923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onFinishInput(); 823a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 824979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 825979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 826b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.flushVoiceInputLogs(mConfigurationChanging); 827409220583333bdf06290dd9fd42f91b5c0d1b11asatok 828f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 829d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa if (inputView != null) inputView.closing(); 830f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard if (mUserUnigramDictionary != null) mUserUnigramDictionary.flushPendingWrites(); 831979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mUserBigramDictionary != null) mUserBigramDictionary.flushPendingWrites(); 832466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 833466741d8a78965b8509bf527344f289e50873092Mike LeBeau 83459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void onFinishInputViewInternal(boolean finishingInput) { 8356495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa super.onFinishInputView(finishingInput); 836055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka mKeyboardSwitcher.onFinishInputView(); 837f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 8385f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka if (inputView != null) inputView.cancelAllMessages(); 839d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka // Remove pending messages related to update suggestions 840d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 8416495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa } 8426495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa 8436495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa @Override 844466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onUpdateExtractedText(int token, ExtractedText text) { 845466741d8a78965b8509bf527344f289e50873092Mike LeBeau super.onUpdateExtractedText(token, text); 846b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.showPunctuationHintIfNecessary(); 847923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 848923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 849923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 850923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onUpdateSelection(int oldSelStart, int oldSelEnd, 851923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int newSelStart, int newSelEnd, 852104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard int composingSpanStart, int composingSpanEnd) { 853923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, 854104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard composingSpanStart, composingSpanEnd); 855466741d8a78965b8509bf527344f289e50873092Mike LeBeau 856466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (DEBUG) { 857466741d8a78965b8509bf527344f289e50873092Mike LeBeau Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart 858466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ose=" + oldSelEnd 859025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lss=" + mLastSelectionStart 860025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lse=" + mLastSelectionEnd 861466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nss=" + newSelStart 862466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nse=" + newSelEnd 863104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard + ", cs=" + composingSpanStart 864104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard + ", ce=" + composingSpanEnd); 865466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 866466741d8a78965b8509bf527344f289e50873092Mike LeBeau 867b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.setCursorAndSelection(newSelEnd, newSelStart); 8684f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 869104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // TODO: refactor the following code to be less contrived. 870104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // "newSelStart != composingSpanEnd" || "newSelEnd != composingSpanEnd" means 871104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // that the cursor is not at the end of the composing span, or there is a selection. 872104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // "mLastSelectionStart != newSelStart" means that the cursor is not in the same place 873104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // as last time we were called (if there is a selection, it means the start hasn't 874104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // changed, so it's the end that did). 875104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard final boolean selectionChanged = (newSelStart != composingSpanEnd 876104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard || newSelEnd != composingSpanEnd) && mLastSelectionStart != newSelStart; 877104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // if composingSpanStart and composingSpanEnd are -1, it means there is no composing 878104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // span in the view - we can use that to narrow down whether the cursor was moved 879104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // by us or not. If we are composing a word but there is no composing span, then 880104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // we know for sure the cursor moved while we were composing and we should reset 881104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // the state. 882104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard final boolean noComposingSpan = composingSpanStart == -1 && composingSpanEnd == -1; 8834733609947c0ec74e460bd714fffca0518ade93aJean Chalard if (!mExpectingUpdateSelection) { 884cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard // TAKE CARE: there is a race condition when we enter this test even when the user 885cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard // did not explicitly move the cursor. This happens when typing fast, where two keys 886cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard // turn this flag on in succession and both onUpdateSelection() calls arrive after 887cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard // the second one - the first call successfully avoids this test, but the second one 888104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // enters. For the moment we rely on noComposingSpan to further reduce the impact. 88951fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard 8909a2a11e65bd32d82754b3fcff74e9e3795327628Jean Chalard // TODO: the following is probably better done in resetEntireInputState(). 8919a2a11e65bd32d82754b3fcff74e9e3795327628Jean Chalard // it should only happen when the cursor moved, and the very purpose of the 8929a2a11e65bd32d82754b3fcff74e9e3795327628Jean Chalard // test below is to narrow down whether this happened or not. Likewise with 8939a2a11e65bd32d82754b3fcff74e9e3795327628Jean Chalard // the call to postUpdateShiftState. 89451fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard // We set this to NONE because after a cursor move, we don't want the space 89551fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard // state-related special processing to kick in. 89651fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard mSpaceState = SPACE_STATE_NONE; 89751fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard 8988a3d369840d6061692a19ceb1eb7267a50a9e056Jean Chalard if ((!mWordComposer.isComposingWord()) || selectionChanged || noComposingSpan) { 8992649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard resetEntireInputState(); 9004c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard } 901beb08b398fa73a26f2d42d6feec87e34a96ca2d9Tadashi G. Takaoka 902beb08b398fa73a26f2d42d6feec87e34a96ca2d9Tadashi G. Takaoka mHandler.postUpdateShiftState(); 9034733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 9044733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = false; 9056b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // TODO: Decide to call restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() or not 9066b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // here. It would probably be too expensive to call directly here but we may want to post a 9076b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // message to delay it. The point would be to unify behavior between backspace to the 9086b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // end of a word and manually put the pointer at the end of the word. 909466741d8a78965b8509bf527344f289e50873092Mike LeBeau 910979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Make a note of the cursor position 911979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionStart = newSelStart; 912979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionEnd = newSelEnd; 9137a8dac55278cedd838be325f56b4c52d973c61f5satok } 9147a8dac55278cedd838be325f56b4c52d973c61f5satok 915c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 916c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has clicked on the extracted text view, 917c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * when running in fullscreen mode. The default implementation hides 918913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * the suggestions view when this happens, but only if the extracted text 919c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * editor has a vertical scroll bar because its text doesn't fit. 920c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 921913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * cause the suggestions strip to disappear and re-appear. 922c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 923c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 924c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedTextClicked() { 925fe5364c825058f6c34c0f42135a5520b77525a28Jean Chalard if (isSuggestionsRequested()) return; 926c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 927c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedTextClicked(); 928c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 929c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 930c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 931c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has performed a cursor movement in the 932c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * extracted text view, when it is running in fullscreen mode. The default 933913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * implementation hides the suggestions view when a vertical movement 934c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * happens, but only if the extracted text editor has a vertical scroll bar 935c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * because its text doesn't fit. 936c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 937913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * cause the suggestions strip to disappear and re-appear. 938c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 939c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 940c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedCursorMovement(int dx, int dy) { 941fe5364c825058f6c34c0f42135a5520b77525a28Jean Chalard if (isSuggestionsRequested()) return; 942c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 943c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedCursorMovement(dx, dy); 944c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 945c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 946923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 947923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void hideWindow() { 948979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 949c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka mKeyboardSwitcher.onHideWindow(); 950979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 951923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (TRACE) Debug.stopMethodTracing(); 9526e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mOptionsDialog != null && mOptionsDialog.isShowing()) { 9536e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog.dismiss(); 9546e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog = null; 9556e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 956b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.hideVoiceWindow(mConfigurationChanging); 957923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.hideWindow(); 958923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 959923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 960923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 9611b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka public void onDisplayCompletions(CompletionInfo[] applicationSpecifiedCompletions) { 962979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (DEBUG) { 963a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa Log.i(TAG, "Received completions:"); 964bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok if (applicationSpecifiedCompletions != null) { 965bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok for (int i = 0; i < applicationSpecifiedCompletions.length; i++) { 966bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok Log.i(TAG, " #" + i + ": " + applicationSpecifiedCompletions[i]); 967bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok } 968923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 969923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 970dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard if (mInputAttributes.mApplicationSpecifiedCompletionOn) { 9711b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletions = applicationSpecifiedCompletions; 9721b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (applicationSpecifiedCompletions == null) { 973b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani clearSuggestions(); 974923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 975923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 976a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 9777e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords.Builder builder = new SuggestedWords.Builder() 9781b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka .setApplicationSpecifiedCompletions(applicationSpecifiedCompletions) 9795238df54ad3f648d09d5288f00b0a9d3c0593832Tadashi G. Takaoka .setTypedWordValid(false) 9805238df54ad3f648d09d5288f00b0a9d3c0593832Tadashi G. Takaoka .setHasMinimalSuggestion(false); 981979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // When in fullscreen mode, show completions generated by the application 9827e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(builder.build()); 983b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard // TODO: is this the right thing to do? What should we auto-correct to in 984b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard // this case? This says to keep whatever the user typed. 985b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard mWordComposer.setAutoCorrection(mWordComposer.getTypedWord()); 986c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShown(true); 987923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 988923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 989923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 990c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka private void setSuggestionStripShownInternal(boolean shown, boolean needsInputViewShown) { 991913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka // TODO: Modify this if we support suggestions with hard keyboard 992913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (onEvaluateInputViewShown() && mSuggestionsContainer != null) { 993433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka final LatinKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); 994433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka final boolean inputViewShown = (keyboardView != null) ? keyboardView.isShown() : false; 995913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka final boolean shouldShowSuggestions = shown 996433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka && (needsInputViewShown ? inputViewShown : true); 9974b1780fa9571409d65d9797d47949ffafaf0f083Tadashi G. Takaoka if (isFullscreenMode()) { 998913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsContainer.setVisibility( 999913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka shouldShowSuggestions ? View.VISIBLE : View.GONE); 10007a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka } else { 1001913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsContainer.setVisibility( 1002913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka shouldShowSuggestions ? View.VISIBLE : View.INVISIBLE); 10037a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka } 1004923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1005923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1006a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1007c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka private void setSuggestionStripShown(boolean shown) { 1008c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShownInternal(shown, /* needsInputViewShown */true); 1009543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa } 1010543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa 1011543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa @Override 1012923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onComputeInsets(InputMethodService.Insets outInsets) { 1013923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onComputeInsets(outInsets); 1014f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka final KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 1015913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (inputView == null || mSuggestionsContainer == null) 101646ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka return; 1017d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka // In fullscreen mode, the height of the extract area managed by InputMethodService should 1018d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka // be considered. 1019d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka // See {@link android.inputmethodservice.InputMethodService#onComputeInsets}. 1020d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka final int extractHeight = isFullscreenMode() ? mExtractArea.getHeight() : 0; 1021abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka final int backingHeight = (mKeyPreviewBackingView.getVisibility() == View.GONE) ? 0 1022abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka : mKeyPreviewBackingView.getHeight(); 102359010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka final int suggestionsHeight = (mSuggestionsContainer.getVisibility() == View.GONE) ? 0 102459010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka : mSuggestionsContainer.getHeight(); 1025d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka final int extraHeight = extractHeight + backingHeight + suggestionsHeight; 1026abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka int touchY = extraHeight; 10279e347d3d448e48229c46aad394ec9bd60cd5807bsatok // Need to set touchable region only if input view is being shown 1028433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka final LatinKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); 1029433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka if (keyboardView != null && keyboardView.isShown()) { 1030913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsContainer.getVisibility() == View.VISIBLE) { 103159010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka touchY -= suggestionsHeight; 10329e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 10337a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka final int touchWidth = inputView.getWidth(); 1034abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka final int touchHeight = inputView.getHeight() + extraHeight 10357a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // Extend touchable region below the keyboard. 10367a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka + EXTENDED_TOUCHABLE_REGION_HEIGHT; 10379e347d3d448e48229c46aad394ec9bd60cd5807bsatok if (DEBUG) { 10387a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka Log.d(TAG, "Touchable region: y=" + touchY + " width=" + touchWidth 10397a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka + " height=" + touchHeight); 10409e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 10417a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka setTouchableRegionCompat(outInsets, 0, touchY, touchWidth, touchHeight); 10429e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 104346ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka outInsets.contentTopInsets = touchY; 104446ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka outInsets.visibleTopInsets = touchY; 1045923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1046a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1047923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 1048979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public boolean onEvaluateFullscreenMode() { 10499751a626ec9b2e771afa5b3757e8f8498a328683Tadashi G. Takaoka // Reread resource value here, because this method is called by framework anytime as needed. 10509751a626ec9b2e771afa5b3757e8f8498a328683Tadashi G. Takaoka final boolean isFullscreenModeAllowed = 10519751a626ec9b2e771afa5b3757e8f8498a328683Tadashi G. Takaoka mSettingsValues.isFullscreenModeAllowed(getResources()); 10529751a626ec9b2e771afa5b3757e8f8498a328683Tadashi G. Takaoka return super.onEvaluateFullscreenMode() && isFullscreenModeAllowed; 105359010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka } 105459010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka 105559010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka @Override 105659010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka public void updateFullscreenMode() { 105759010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka super.updateFullscreenMode(); 1058f80b6a06992ae08ca3601f4fbc6da550fd9ac730Tadashi G. Takaoka 105959010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka if (mKeyPreviewBackingView == null) return; 1060549e295dc113bff50077c3c355dcd94af09a1b2fTadashi G. Takaoka // In fullscreen mode, no need to have extra space to show the key preview. 106159010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka // If not, we should have extra space above the keyboard to show the key preview. 1062549e295dc113bff50077c3c355dcd94af09a1b2fTadashi G. Takaoka mKeyPreviewBackingView.setVisibility(isFullscreenMode() ? View.GONE : View.VISIBLE); 1063979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1064979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1065979f8690967ff5409fe18f5085858ccdb8e0ccf1satok @Override 1066923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 1067923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 1068e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_BACK: 10692cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka if (event.getRepeatCount() == 0) { 10702cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka if (mSuggestionsView != null && mSuggestionsView.handleBack()) { 10712cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka return true; 10722cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka } 10732cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka final LatinKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); 10742cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka if (keyboardView != null && keyboardView.handleBack()) { 10756e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani return true; 10766e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 1077e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 1078e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 1079923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1080923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyDown(keyCode, event); 1081923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1082923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1083923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 1084923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 1085923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 1086e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_DOWN: 1087e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_UP: 1088e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_LEFT: 1089e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_RIGHT: 1090433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka final LatinKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); 1091433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); 1092e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka // Enable shift key and DPAD to do selections 1093433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka if ((keyboardView != null && keyboardView.isShown()) 1094433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka && (keyboard != null && keyboard.isShiftedOrShiftLocked())) { 1095e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent newEvent = new KeyEvent(event.getDownTime(), event.getEventTime(), 1096e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getAction(), event.getKeyCode(), event.getRepeatCount(), 1097e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getDeviceId(), event.getScanCode(), 1098e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON); 10999351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1100e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (ic != null) 1101e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka ic.sendKeyEvent(newEvent); 1102e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka return true; 1103e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 1104e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 1105923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1106923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyUp(keyCode, event); 1107923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1108923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 11092649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard // This will reset the whole input state to the starting state. It will clear 11102649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard // the composing word, reset the last composed word, tell the inputconnection 11112649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard // and the composingStateManager about it. 11122649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard private void resetEntireInputState() { 11132649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard resetComposingState(true /* alsoResetLastComposedWord */); 11142649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard updateSuggestions(); 11152649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard final InputConnection ic = getCurrentInputConnection(); 11162649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard if (ic != null) { 11172649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard ic.finishComposingText(); 11182649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard } 11192649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard mComposingStateManager.onFinishComposingText(); 11202649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard mVoiceProxy.setVoiceInputHighlighted(false); 11212649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard } 11222649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard 11232692a8700737d8eed268039aa27b22a31669da08Jean Chalard private void resetComposingState(final boolean alsoResetLastComposedWord) { 11242692a8700737d8eed268039aa27b22a31669da08Jean Chalard mWordComposer.reset(); 11252692a8700737d8eed268039aa27b22a31669da08Jean Chalard if (alsoResetLastComposedWord) 11262692a8700737d8eed268039aa27b22a31669da08Jean Chalard mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; 11272692a8700737d8eed268039aa27b22a31669da08Jean Chalard } 11282692a8700737d8eed268039aa27b22a31669da08Jean Chalard 112966bb563535dbe3672f99f75bd71763a551444867Jean Chalard public void commitTyped(final InputConnection ic, final int separatorCode) { 1130196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (!mWordComposer.isComposingWord()) return; 11313651220327c051d8017045aa5e8919461507b3f8Jean Chalard final CharSequence typedWord = mWordComposer.getTypedWord(); 11323651220327c051d8017045aa5e8919461507b3f8Jean Chalard if (typedWord.length() > 0) { 1133cf9d92629cae88273805eaf7984fcfdd8afd11f5Jean Chalard mLastComposedWord = mWordComposer.commitWord( 113466bb563535dbe3672f99f75bd71763a551444867Jean Chalard LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, typedWord.toString(), 113566bb563535dbe3672f99f75bd71763a551444867Jean Chalard separatorCode); 11369351550dc6af7859e5280e16144c9386a37b976dKen Wakasa if (ic != null) { 11373651220327c051d8017045aa5e8919461507b3f8Jean Chalard ic.commitText(typedWord, 1); 1138923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 11393651220327c051d8017045aa5e8919461507b3f8Jean Chalard addToUserUnigramAndBigramDictionaries(typedWord, 1140f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard UserUnigramDictionary.FREQUENCY_FOR_TYPED); 1141923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 11428558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa updateSuggestions(); 1143923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1144923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1145b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public boolean getCurrentAutoCapsState() { 11469351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 11471c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani EditorInfo ei = getCurrentInputEditorInfo(); 114817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.mAutoCap && ic != null && ei != null 114917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && ei.inputType != InputType.TYPE_NULL) { 1150b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return ic.getCursorCapsMode(ei.inputType) != 0; 11511c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 1152b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 11531c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 11541c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 1155b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard // "ic" may be null 1156b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard private void swapSwapperAndSpaceWhileInBatchEdit(final InputConnection ic) { 1157b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard if (null == ic) return; 1158923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence lastTwo = ic.getTextBeforeCursor(2, 0); 1159863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called. 1160923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastTwo != null && lastTwo.length() == 2 1161863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard && lastTwo.charAt(0) == Keyboard.CODE_SPACE) { 1162923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 1163923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(lastTwo.charAt(1) + " ", 1); 1164b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 11654ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 11664ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 11674ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1168120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private boolean maybeDoubleSpaceWhileInBatchEdit(final InputConnection ic) { 1169120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (mCorrectionMode == Suggest.CORRECTION_NONE) return false; 1170120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (ic == null) return false; 11712b4eabed2bfe982b91a994c145401d98894e6ef5Jean Chalard final CharSequence lastThree = ic.getTextBeforeCursor(3, 0); 1172923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastThree != null && lastThree.length() == 3 11739351550dc6af7859e5280e16144c9386a37b976dKen Wakasa && Utils.canBeFollowedByPeriod(lastThree.charAt(0)) 1174571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(1) == Keyboard.CODE_SPACE 1175fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka && lastThree.charAt(2) == Keyboard.CODE_SPACE 1176fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka && mHandler.isAcceptingDoubleSpaces()) { 1177fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka mHandler.cancelDoubleSpacesTimer(); 1178923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 1179923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(". ", 1); 1180b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1181120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return true; 1182923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1183120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return false; 1184923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1185a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1186b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard // "ic" may be null 11878fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka private static void removeTrailingSpaceWhileInBatchEdit(final InputConnection ic) { 11889a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic == null) return; 1189b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard final CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 11909a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (lastOne != null && lastOne.length() == 1 1191571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastOne.charAt(0) == Keyboard.CODE_SPACE) { 11929a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.deleteSurroundingText(1, 0); 11939a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 11949a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 11959a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa 1196c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka @Override 1197923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean addWordToDictionary(String word) { 1198923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mUserDictionary.addWord(word, 128); 11996558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Suggestion strip should be updated after the operation of adding word to the 12006558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // user dictionary 1201d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1202923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1203923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1204923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 12058fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka private static boolean isAlphabet(int code) { 12068fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka return Character.isLetter(code); 1207923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1208a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1209e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka private void onSettingsKeyPressed() { 1210cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa if (isShowingOptionDialog()) return; 1211d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) { 1212d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka showSubtypeSelectorAndSettings(); 121323d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka } else if (Utils.hasMultipleEnabledIMEsOrSubtypes(false /* exclude aux subtypes */)) { 1214d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka showOptionsMenu(); 1215d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka } else { 1216d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka launchSettings(); 12179a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 12189a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 12199a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 1220cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa // Virtual codes representing custom requests. These are used in onCustomRequest() below. 1221cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa public static final int CODE_SHOW_INPUT_METHOD_PICKER = 1; 1222d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka public static final int CODE_HAPTIC_AND_AUDIO_FEEDBACK = 2; 1223cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa 1224cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa @Override 1225cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa public boolean onCustomRequest(int requestCode) { 1226cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa if (isShowingOptionDialog()) return false; 1227cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa switch (requestCode) { 1228cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa case CODE_SHOW_INPUT_METHOD_PICKER: 122923d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka if (Utils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */)) { 123079efbed76f638be298493107fa2d0cd1b5eb529esatok mImm.showInputMethodPicker(); 1231cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return true; 12329a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 1233cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return false; 1234d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka case CODE_HAPTIC_AND_AUDIO_FEEDBACK: 1235d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka hapticAndAudioFeedback(Keyboard.CODE_UNSPECIFIED); 1236d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka return true; 12379a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 1238cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return false; 12399a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 12409a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 12419a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok private boolean isShowingOptionDialog() { 12429a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok return mOptionsDialog != null && mOptionsDialog.isShowing(); 12439a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 12449a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 12457a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka private void insertPunctuationFromSuggestionStrip(final int code) { 12467a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka onCodeInput(code, new int[] { code }, 12477a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka KeyboardActionListener.SUGGESTION_STRIP_COORDINATE, 12487a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka KeyboardActionListener.SUGGESTION_STRIP_COORDINATE); 12497a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 12507a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka 12517a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka private static int getEditorActionId(EditorInfo editorInfo) { 12527a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka if (editorInfo == null) return 0; 12537a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka return (editorInfo.actionLabel != null) 12547a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka ? editorInfo.actionId 12557a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka : (editorInfo.imeOptions & EditorInfo.IME_MASK_ACTION); 12567a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 12577a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka 12587a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka private void performeEditorAction(int actionId) { 12597a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 12607a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka if (ic != null) { 12617a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka ic.performEditorAction(actionId); 12627a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 12637a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 12647a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka 12657a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka private void sendKeyCodePoint(int code) { 12667a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka // TODO: Remove this special handling of digit letters. 12677a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka // For backward compatibility. See {@link InputMethodService#sendKeyChar(char)}. 12687a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka if (code >= '0' && code <= '9') { 12697a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka super.sendKeyChar((char)code); 12707a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka return; 12717a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 12727a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka 12737a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 12747a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka if (ic != null) { 12757a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka final String text = new String(new int[] { code }, 0, 1); 12767a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka ic.commitText(text, text.length()); 12777a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 12787a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 12797a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka 12805f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // Implementation of {@link KeyboardActionListener}. 12815a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 12828aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { 1283175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka final long when = SystemClock.uptimeMillis(); 1284571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) { 1285923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mDeleteCount = 0; 1286923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1287923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastKeyTime = when; 1288175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 1289120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // The space state depends only on the last character pressed and its own previous 1290120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // state. Here, we revert the space state to neutral if the key is actually modifying 1291120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // the input contents (any non-shift key), which is what we should do for 1292120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // all inputs that do not result in a special state. Each character handling is then 1293120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // free to override the state as they see fit. 1294120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final int spaceState = mSpaceState; 1295ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa 1296ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa // TODO: Consolidate the double space timer, mLastKeyTime, and the space state. 1297ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa if (primaryCode != Keyboard.CODE_SPACE) { 1298ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa mHandler.cancelDoubleSpacesTimer(); 1299ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa } 1300ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa 1301c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard boolean didAutoCorrect = false; 1302923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 1303571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_DELETE: 1304120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 1305120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard handleBackspace(spaceState); 13064189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka mDeleteCount++; 13074733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 13084189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka LatinImeLogger.logOnDelete(); 13094189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1310571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_SHIFT: 1311e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: 13122a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka // Shift and symbol key is handled in onPressKey() and onReleaseKey(). 13134189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1314e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SETTINGS: 131593246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka onSettingsKeyPressed(); 13164189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1317d2c5fdda862f6dd2a1e020cf674c35fbbc63fc92Tadashi G. Takaoka case Keyboard.CODE_SHORTCUT: 131893246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka mSubtypeSwitcher.switchToShortcutIME(); 13194189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 13207a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka case Keyboard.CODE_ACTION_ENTER: 13217a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka performeEditorAction(getEditorActionId(getCurrentInputEditorInfo())); 13227a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka break; 1323571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_TAB: 132445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka handleTab(); 13254733609947c0ec74e460bd714fffca0518ade93aJean Chalard // There are two cases for tab. Either we send a "next" event, that may change the 13264733609947c0ec74e460bd714fffca0518ade93aJean Chalard // focus but will never move the cursor. Or, we send a real tab keycode, which some 13274733609947c0ec74e460bd714fffca0518ade93aJean Chalard // applications may accept or ignore, and we don't know whether this will move the 13284733609947c0ec74e460bd714fffca0518ade93aJean Chalard // cursor or not. So actually, we don't really know. 13294733609947c0ec74e460bd714fffca0518ade93aJean Chalard // So to go with the safer option, we'd rather behave as if the user moved the 13304733609947c0ec74e460bd714fffca0518ade93aJean Chalard // cursor when they didn't than the opposite. We also expect that most applications 13314733609947c0ec74e460bd714fffca0518ade93aJean Chalard // will actually use tab only for focus movement. 13324733609947c0ec74e460bd714fffca0518ade93aJean Chalard // To sum it up: do not update mExpectingUpdateSelection here. 13334189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 13344189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka default: 1335120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 133617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.isWordSeparator(primaryCode)) { 1337c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState); 13384189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } else { 1339120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard handleCharacter(primaryCode, keyCodes, x, y, spaceState); 13404189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 13414733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 13424733609947c0ec74e460bd714fffca0518ade93aJean Chalard break; 1343923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1344eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka switcher.onCodeInput(primaryCode); 1345dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Reset after any single keystroke 1346c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard if (!didAutoCorrect) 1347c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard mLastComposedWord.deactivate(); 1348dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = null; 1349923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1350a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 13515a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 13528aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onTextInput(CharSequence text) { 1353b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.commitVoiceInput(); 13549351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1355923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 1356923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 135766bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitTyped(ic, LastComposedWord.NOT_A_SEPARATOR); 1358fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard text = specificTldProcessingOnTextInput(ic, text); 1359fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (SPACE_STATE_PHANTOM == mSpaceState) { 13607a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka sendKeyCodePoint(Keyboard.CODE_SPACE); 1361fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 1362923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(text, 1); 1363923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1364b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 13658cab0b56eb8db311f158b18a361d9ceb85cff482Tadashi G. Takaoka mKeyboardSwitcher.onCodeInput(Keyboard.CODE_OUTPUT_TEXT); 1366120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 1367dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = text; 13682692a8700737d8eed268039aa27b22a31669da08Jean Chalard resetComposingState(true /* alsoResetLastComposedWord */); 1369923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1370923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1371fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // ic may not be null 1372fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard private CharSequence specificTldProcessingOnTextInput(final InputConnection ic, 1373fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard final CharSequence text) { 1374fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (text.length() <= 1 || text.charAt(0) != Keyboard.CODE_PERIOD 1375fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard || !Character.isLetter(text.charAt(1))) { 1376fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // Not a tld: do nothing. 1377fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard return text; 1378fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 137912d67e6d5d5bd764117038f3f666d4d7da0c10eaJean Chalard // We have a TLD (or something that looks like this): make sure we don't add 138012d67e6d5d5bd764117038f3f666d4d7da0c10eaJean Chalard // a space even if currently in phantom mode. 138112d67e6d5d5bd764117038f3f666d4d7da0c10eaJean Chalard mSpaceState = SPACE_STATE_NONE; 1382fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard final CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 1383fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (lastOne != null && lastOne.length() == 1 1384fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard && lastOne.charAt(0) == Keyboard.CODE_PERIOD) { 1385fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard return text.subSequence(1, text.length()); 1386fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } else { 1387fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard return text; 1388fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 1389fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 1390fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard 13915a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 13928aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCancelInput() { 139383e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka // User released a finger outside any key 13945f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka mKeyboardSwitcher.onCancelInput(); 139583e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka } 139683e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka 1397120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private void handleBackspace(final int spaceState) { 1398b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok if (mVoiceProxy.logAndRevertVoiceInput()) return; 1399504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1400504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (ic == null) return; 1401979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.beginBatchEdit(); 1402a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard handleBackspaceWhileInBatchEdit(spaceState, ic); 1403a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard ic.endBatchEdit(); 1404a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard } 1405979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1406a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard // "ic" may not be null. 1407a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard private void handleBackspaceWhileInBatchEdit(final int spaceState, final InputConnection ic) { 1408b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleBackspace(); 14094f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 14102245c3b5b3691928b08fd6accf8d4a21fb35e26bJean Chalard // In many cases, we may have to put the keyboard in auto-shift state again. 1411beb08b398fa73a26f2d42d6feec87e34a96ca2d9Tadashi G. Takaoka mHandler.postUpdateShiftState(); 14122245c3b5b3691928b08fd6accf8d4a21fb35e26bJean Chalard 14135c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { 14145c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // Cancel multi-character input: remove the text we just entered. 14155c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // This is triggered on backspace after a key that inputs multiple characters, 14165c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // like the smiley key or the .com key. 14175c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard ic.deleteSurroundingText(mEnteredText.length(), 0); 14185c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // If we have mEnteredText, then we know that mHasUncommittedTypedChars == false. 14195c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // In addition we know that spaceState is false, and that we should not be 14205c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // reverting any autocorrect at this point. So we can safely return. 14215c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard return; 14225c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard } 14235c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard 1424196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (mWordComposer.isComposingWord()) { 14253651220327c051d8017045aa5e8919461507b3f8Jean Chalard final int length = mWordComposer.size(); 1426923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (length > 0) { 14279318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.deleteLast(); 142877d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); 1429196d82cdd740580ed79d801483dbc282be85d076Jean Chalard // If we have deleted the last remaining character of a word, then we are not 1430196d82cdd740580ed79d801483dbc282be85d076Jean Chalard // isComposingWord() any more. 1431196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (!mWordComposer.isComposingWord()) { 1432196d82cdd740580ed79d801483dbc282be85d076Jean Chalard // Not composing word any more, so we can show bigrams. 1433cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.postUpdateBigramPredictions(); 143489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 1435196d82cdd740580ed79d801483dbc282be85d076Jean Chalard // Still composing a word, so we still have letters to deduce a suggestion from. 143689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.postUpdateSuggestions(); 143789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 1438923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1439923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(1, 0); 1440923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1441890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard } else { 144272d285f4d758dd1ceafb7d9bd3dd330efd24c1f8Jean Chalard // We should be very careful about auto-correction cancellation and suggestion 144372d285f4d758dd1ceafb7d9bd3dd330efd24c1f8Jean Chalard // resuming here. The behavior needs to be different according to text field types, 144472d285f4d758dd1ceafb7d9bd3dd330efd24c1f8Jean Chalard // and it would be much clearer to test for them explicitly here rather than 144572d285f4d758dd1ceafb7d9bd3dd330efd24c1f8Jean Chalard // relying on implicit values like "whether the suggestion strip is displayed". 1446b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard if (mLastComposedWord.canCancelAutoCorrect()) { 1447d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard Utils.Stats.onAutoCorrectionCancellation(); 1448d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard cancelAutoCorrect(ic); 1449120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return; 1450120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1451d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard 1452d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard if (SPACE_STATE_DOUBLE == spaceState) { 14532124bc5bf5af31cf3d2789b70ebd2f24c815f5f4Jean Chalard if (revertDoubleSpaceWhileInBatchEdit(ic)) { 1454d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard // No need to reset mSpaceState, it has already be done (that's why we 1455d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard // receive it as a parameter) 1456d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard return; 1457d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard } 1458d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard } else if (SPACE_STATE_SWAP_PUNCTUATION == spaceState) { 1459d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard if (revertSwapPunctuation(ic)) { 1460d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard // Likewise 1461d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard return; 1462d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard } 14634733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 1464504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka 146572d285f4d758dd1ceafb7d9bd3dd330efd24c1f8Jean Chalard // See the comment above: must be careful about resuming auto-suggestion. 1466913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) { 14676558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Go back to the suggestion mode if the user canceled the 146855b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // "Touch again to save". 1469a8ba49c2534220105ce302a50b3a9ddaf831ef20Jean Chalard // NOTE: In general, we don't revert the word when backspacing 14706558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // from a manual suggestion pick. We deliberately chose a 14716558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // different behavior only in the case of picking the first 14726558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // suggestion (typed word). It's intentional to have made this 14736558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // inconsistent with backspacing after selecting other suggestions. 1474890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard restartSuggestionsOnManuallyPickedTypedWord(ic); 14756558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } else { 147677da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard // Here we must check whether there is a selection. If so we should remove the 147777da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard // selected text, otherwise we should just delete the character before the cursor. 147877da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard if (mLastSelectionStart != mLastSelectionEnd) { 147977da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard final int lengthToDelete = mLastSelectionEnd - mLastSelectionStart; 148077da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard ic.setSelection(mLastSelectionEnd, mLastSelectionEnd); 148177da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard ic.deleteSurroundingText(lengthToDelete, 0); 148277da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard } else { 148377da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard if (NOT_A_CURSOR_POSITION == mLastSelectionEnd) { 14841fead1d5f12928f90c723b5f7b88490cc7cd2a67Jean Chalard // This should never happen. 14851fead1d5f12928f90c723b5f7b88490cc7cd2a67Jean Chalard Log.e(TAG, "Backspace when we don't know the selection position"); 148677da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard } 14871fead1d5f12928f90c723b5f7b88490cc7cd2a67Jean Chalard ic.deleteSurroundingText(1, 0); 148877da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard if (mDeleteCount > DELETE_ACCELERATE_AT) { 148977da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard ic.deleteSurroundingText(1, 0); 149077da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard } 14916558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 1492edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard if (isSuggestionsRequested()) { 1493edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard restartSuggestionsOnWordBeforeCursorIfAtEndOfWord(ic); 1494edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard } 1495923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1496923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1497923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1498923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 14997a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka // TODO: Implement next and previous actions using other key code than tab's code. 150045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka private void handleTab() { 150145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final int imeOptions = getCurrentInputEditorInfo().imeOptions; 1502b2707856aba4fc9b063f26305f1fb603b19c1701satok if (!EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) 1503b2707856aba4fc9b063f26305f1fb603b19c1701satok && !EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions)) { 15047a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka // TODO: This should be {@link #sendKeyCodePoint(int)}. 150545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB); 150645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka return; 150745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 150845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 150945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 151045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (ic == null) 151145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka return; 151245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 1513ca2f051cc173acc3bce384ebfe08068564bc8e07Tadashi G. Takaoka final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); 1514ca2f051cc173acc3bce384ebfe08068564bc8e07Tadashi G. Takaoka // True if keyboard is in either shift chording or manual shifted state. 1515ca2f051cc173acc3bce384ebfe08068564bc8e07Tadashi G. Takaoka final boolean isManualShifted = (keyboard != null && keyboard.isManualShifted()); 1516ca2f051cc173acc3bce384ebfe08068564bc8e07Tadashi G. Takaoka if (EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) && !isManualShifted) { 1517b2707856aba4fc9b063f26305f1fb603b19c1701satok EditorInfoCompatUtils.performEditorActionNext(ic); 1518ca2f051cc173acc3bce384ebfe08068564bc8e07Tadashi G. Takaoka } else if (EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions) && isManualShifted) { 1519b2707856aba4fc9b063f26305f1fb603b19c1701satok EditorInfoCompatUtils.performEditorActionPrevious(ic); 152045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 152145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 152245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 1523e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard // ic may be null 1524e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard private boolean maybeStripSpaceWhileInBatchEdit(final InputConnection ic, final int code, 1525e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard final int spaceState, final boolean isFromSuggestionStrip) { 1526e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard if (Keyboard.CODE_ENTER == code && SPACE_STATE_SWAP_PUNCTUATION == spaceState) { 1527e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard removeTrailingSpaceWhileInBatchEdit(ic); 1528e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard return false; 1529e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } else if ((SPACE_STATE_WEAK == spaceState 1530e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard || SPACE_STATE_SWAP_PUNCTUATION == spaceState) 1531e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard && isFromSuggestionStrip) { 1532b141c9cd3f6785bc0a4e1f5385f4e6e2e17955bbJean Chalard if (mSettingsValues.isWeakSpaceSwapper(code)) { 1533e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard return true; 1534e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } else { 1535b141c9cd3f6785bc0a4e1f5385f4e6e2e17955bbJean Chalard if (mSettingsValues.isWeakSpaceStripper(code)) { 1536e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard removeTrailingSpaceWhileInBatchEdit(ic); 1537e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 1538e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard return false; 1539e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 1540e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } else { 1541e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard return false; 1542e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 1543e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 1544e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard 1545120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private void handleCharacter(final int primaryCode, final int[] keyCodes, final int x, 1546120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final int y, final int spaceState) { 1547b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleCharacter(); 1548b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard final InputConnection ic = getCurrentInputConnection(); 1549dafa7a8e15447544842975047f831883e67700c5Jean Chalard if (null != ic) ic.beginBatchEdit(); 1550dafa7a8e15447544842975047f831883e67700c5Jean Chalard // TODO: if ic is null, does it make any sense to call this? 1551dafa7a8e15447544842975047f831883e67700c5Jean Chalard handleCharacterWhileInBatchEdit(primaryCode, keyCodes, x, y, spaceState, ic); 1552dafa7a8e15447544842975047f831883e67700c5Jean Chalard if (null != ic) ic.endBatchEdit(); 1553dafa7a8e15447544842975047f831883e67700c5Jean Chalard } 1554dafa7a8e15447544842975047f831883e67700c5Jean Chalard 1555dafa7a8e15447544842975047f831883e67700c5Jean Chalard // "ic" may be null without this crashing, but the behavior will be really strange 1556dafa7a8e15447544842975047f831883e67700c5Jean Chalard private void handleCharacterWhileInBatchEdit(final int primaryCode, final int[] keyCodes, 1557dafa7a8e15447544842975047f831883e67700c5Jean Chalard final int x, final int y, final int spaceState, final InputConnection ic) { 1558196d82cdd740580ed79d801483dbc282be85d076Jean Chalard boolean isComposingWord = mWordComposer.isComposingWord(); 1559fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard 1560fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (SPACE_STATE_PHANTOM == spaceState && 1561fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard !mSettingsValues.isSymbolExcludedFromWordSeparators(primaryCode)) { 1562fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (isComposingWord) { 1563fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // Sanity check 1564fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard throw new RuntimeException("Should not be composing here"); 1565fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 15667a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka sendKeyCodePoint(Keyboard.CODE_SPACE); 1567fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 1568fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard 1569e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard if ((isAlphabet(primaryCode) 1570e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard || mSettingsValues.isSymbolExcludedFromWordSeparators(primaryCode)) 15713889462439357fd76c0b82dfd52e1ca6e0bafd2dKen Wakasa && isSuggestionsRequested() && !isCursorTouchingWord()) { 15727b5bc1ff4d4694045e69e6aff8a2b5365ff882d1Jean Chalard if (!isComposingWord) { 15736d1cbbc2ffb9d7046189174ec68b5b72bbc154b3Jean Chalard // Reset entirely the composing state anyway, then start composing a new word unless 15747b5bc1ff4d4694045e69e6aff8a2b5365ff882d1Jean Chalard // the character is a single quote. The idea here is, single quote is not a 15757b5bc1ff4d4694045e69e6aff8a2b5365ff882d1Jean Chalard // separator and it should be treated as a normal character, except in the first 15767b5bc1ff4d4694045e69e6aff8a2b5365ff882d1Jean Chalard // position where it should not start composing a word. 1577e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard isComposingWord = (Keyboard.CODE_SINGLE_QUOTE != primaryCode); 15782692a8700737d8eed268039aa27b22a31669da08Jean Chalard // Here we don't need to reset the last composed word. It will be reset 15792692a8700737d8eed268039aa27b22a31669da08Jean Chalard // when we commit this one, if we ever do; if on the other hand we backspace 15802692a8700737d8eed268039aa27b22a31669da08Jean Chalard // it entirely and resume suggestions on the previous word, we'd like to still 15812692a8700737d8eed268039aa27b22a31669da08Jean Chalard // have touch coordinates for it. 15822692a8700737d8eed268039aa27b22a31669da08Jean Chalard resetComposingState(false /* alsoResetLastComposedWord */); 15837e99a28dfcc14f5b19220442db972ca8d786b4feKen Wakasa clearSuggestions(); 1584604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.onFinishComposingText(); 1585923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1586923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 15877b5bc1ff4d4694045e69e6aff8a2b5365ff882d1Jean Chalard if (isComposingWord) { 1588e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard mWordComposer.add(primaryCode, keyCodes, x, y); 1589923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 15901c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani // If it's the first letter, make note of auto-caps state 15919318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa if (mWordComposer.size() == 1) { 15929318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.setAutoCapitalized(getCurrentAutoCapsState()); 1593604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.onStartComposingText(); 15941c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 159577d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); 1596923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1597d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1598923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1599e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard final boolean swapWeakSpace = maybeStripSpaceWhileInBatchEdit(ic, primaryCode, 1600e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard spaceState, KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x); 1601863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard 16027a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka sendKeyCodePoint(primaryCode); 1603e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard 1604e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard if (swapWeakSpace) { 1605e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard swapSwapperAndSpaceWhileInBatchEdit(ic); 1606e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard mSpaceState = SPACE_STATE_WEAK; 1607e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 16085262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // Some characters are not word separators, yet they don't start a new 16095262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // composing span. For these, we haven't changed the suggestion strip, and 16105262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // if the "add to dictionary" hint is shown, we should do so now. Examples of 16115262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // such characters include single quote, dollar, and others; the exact list is 16125262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // the list of characters for which we enter handleCharacterWhileInBatchEdit 16135262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // that don't match the test if ((isAlphabet...)) at the top of this method. 16145262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard if (null != mSuggestionsView && mSuggestionsView.dismissAddToDictionaryHint()) { 16155262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard mHandler.postUpdateBigramPredictions(); 16165262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard } 1617e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 1618e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard Utils.Stats.onNonSeparator((char)primaryCode, x, y); 1619923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1620923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1621c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard // Returns true if we did an autocorrection, false otherwise. 1622c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard private boolean handleSeparator(final int primaryCode, final int x, final int y, 1623120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final int spaceState) { 1624b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleSeparator(); 1625604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.onFinishComposingText(); 16264f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 162755b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // Should dismiss the "Touch again to save" message when handling separator 1628913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) { 1629cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.cancelUpdateBigramPredictions(); 1630d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 16316558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 16326558253160e2039c87f424bd814f402ecd31de3bKen Wakasa 1633c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard boolean didAutoCorrect = false; 1634923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Handle separator 16351b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1636923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1637923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 1638923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1639196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (mWordComposer.isComposingWord()) { 1640923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In certain languages where single quote is a separator, it's better 1641a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker // not to auto correct, but accept the typed word. For instance, 1642923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // in Italian dov' should not be expanded to dove' because the elision 1643923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // requires the last vowel to be removed. 1644f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled 1645dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard && !mInputAttributes.mInputTypeNoAutoCorrect; 164617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (shouldAutoCorrect && primaryCode != Keyboard.CODE_SINGLE_QUOTE) { 1647f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard commitCurrentAutoCorrection(primaryCode, ic); 1648c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard didAutoCorrect = true; 1649923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 165066bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitTyped(ic, primaryCode); 1651923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1652923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 16534ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1654e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard final boolean swapWeakSpace = maybeStripSpaceWhileInBatchEdit(ic, primaryCode, spaceState, 1655e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x); 1656863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard 16577a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka sendKeyCodePoint(primaryCode); 165889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 165989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (Keyboard.CODE_SPACE == primaryCode) { 1660120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (isSuggestionsRequested()) { 1661120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (maybeDoubleSpaceWhileInBatchEdit(ic)) { 1662120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_DOUBLE; 1663120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } else if (!isShowingPunctuationList()) { 1664120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_WEAK; 1665120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1666126698fdd256a2e3734634d3b923cabd800064baJean Chalard } 1667120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 1668120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mHandler.startDoubleSpacesTimer(); 166989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (!isCursorTouchingWord()) { 167089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.cancelUpdateSuggestions(); 1671cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.postUpdateBigramPredictions(); 167289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 167389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 1674fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (swapWeakSpace) { 1675120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard swapSwapperAndSpaceWhileInBatchEdit(ic); 16764721427c7de3600f6fe7dfff16508a6a974fb3e4Jean Chalard mSpaceState = SPACE_STATE_SWAP_PUNCTUATION; 1677fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } else if (SPACE_STATE_PHANTOM == spaceState) { 1678fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // If we are in phantom space state, and the user presses a separator, we want to 1679fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // stay in phantom space state so that the next keypress has a chance to add the 1680fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // space. For example, if I type "Good dat", pick "day" from the suggestion strip 1681fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // then insert a comma and go on to typing the next word, I want the space to be 1682fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // inserted automatically before the next word, the same way it is when I don't 1683fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // input the comma. 1684fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard mSpaceState = SPACE_STATE_PHANTOM; 1685120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1686120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 168789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Set punctuation right away. onUpdateSelection will fire but tests whether it is 168889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // already displayed or not, so it's okay. 168955b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka setPunctuationSuggestions(); 1690923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1691120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 1692406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard Utils.Stats.onSeparator((char)primaryCode, x, y); 1693120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 1694923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1695923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1696923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1697c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard return didAutoCorrect; 1698923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1699466741d8a78965b8509bf527344f289e50873092Mike LeBeau 170077d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard private CharSequence getTextWithUnderline(final CharSequence text) { 170177d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard return mComposingStateManager.isAutoCorrectionIndicatorOn() 170277d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(this, text) 1703fda847a870829f1491cbd5325f9c985213081149Jean Chalard : text; 170477d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard } 170577d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard 1706923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleClose() { 170766bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitTyped(getCurrentInputConnection(), LastComposedWord.NOT_A_SEPARATOR); 1708b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleClose(); 1709923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project requestHideSelf(0); 1710c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 17111679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka if (inputView != null) 17121679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka inputView.closing(); 1713923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1714923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 17157a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isSuggestionsRequested() { 1716dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard return mInputAttributes.mIsSettingsSuggestionStripOn 1717c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka && (mCorrectionMode > 0 || isShowingSuggestionsStrip()); 1718923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1719a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 17207a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isShowingPunctuationList() { 1721cb8cb95d0afd340de9f1a0e15948f0068d2450bcKen Wakasa if (mSuggestionsView == null) return false; 1722913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka return mSettingsValues.mSuggestPuncList == mSuggestionsView.getSuggestions(); 17237599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 17247599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 17257a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isShowingSuggestionsStrip() { 17267599cfea4a2d56f4779452ec8e8742f7b9629cc0satok return (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_VALUE) 17277599cfea4a2d56f4779452ec8e8742f7b9629cc0satok || (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 172838f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka && mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT); 17297599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 17307599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 1731913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka public boolean isSuggestionsStripVisible() { 1732913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView == null) 1733b5e00d5841b946de8970875231456228ae0eb6b1Ken Wakasa return false; 1734d0c5f9395a1b94e8425982e353d090f972dc44f0Jean Chalard if (mSuggestionsView.isShowingAddToDictionaryHint()) 17359fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 17369fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!isShowingSuggestionsStrip()) 17379fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return false; 1738dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard if (mInputAttributes.mApplicationSpecifiedCompletionOn) 17399fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 17409fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return isSuggestionsRequested(); 1741923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1742923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1743409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void switchToKeyboardView() { 1744060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (DEBUG) { 1745060efb6d82af1f896d90cb845c8ae07c726f85e1satok Log.d(TAG, "Switch to keyboard view."); 1746060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 1747c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka View v = mKeyboardSwitcher.getKeyboardView(); 1748060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (v != null) { 1749060efb6d82af1f896d90cb845c8ae07c726f85e1satok // Confirms that the keyboard view doesn't have parent view. 1750060efb6d82af1f896d90cb845c8ae07c726f85e1satok ViewParent p = v.getParent(); 1751060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (p != null && p instanceof ViewGroup) { 1752060efb6d82af1f896d90cb845c8ae07c726f85e1satok ((ViewGroup) p).removeView(v); 17535a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } 1754060efb6d82af1f896d90cb845c8ae07c726f85e1satok setInputView(v); 1755060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 1756913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShown(isSuggestionsStripVisible()); 1757060efb6d82af1f896d90cb845c8ae07c726f85e1satok updateInputViewShown(); 1758060efb6d82af1f896d90cb845c8ae07c726f85e1satok mHandler.postUpdateSuggestions(); 1759466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1760466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1761409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void clearSuggestions() { 17627e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(SuggestedWords.EMPTY); 1763466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1764466741d8a78965b8509bf527344f289e50873092Mike LeBeau 17657e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka public void setSuggestions(SuggestedWords words) { 1766913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) { 1767913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.setSuggestions(words); 17685e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka mKeyboardSwitcher.onAutoCorrectionStateChanged( 17695e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka words.hasWordAboveAutoCorrectionScoreThreshold()); 1770466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1771ec780e2868962bf17f0dfd35d36895f543bde40asatok 1772ec780e2868962bf17f0dfd35d36895f543bde40asatok // Put a blue underline to a word in TextView which will be auto-corrected. 1773ec780e2868962bf17f0dfd35d36895f543bde40asatok final InputConnection ic = getCurrentInputConnection(); 1774604d80c67185954d4691ac775be59c499eee3b1csatok if (ic != null) { 1775604d80c67185954d4691ac775be59c499eee3b1csatok final boolean oldAutoCorrectionIndicator = 1776604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.isAutoCorrectionIndicatorOn(); 1777604d80c67185954d4691ac775be59c499eee3b1csatok final boolean newAutoCorrectionIndicator = Utils.willAutoCorrect(words); 1778604d80c67185954d4691ac775be59c499eee3b1csatok if (oldAutoCorrectionIndicator != newAutoCorrectionIndicator) { 177977d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard mComposingStateManager.setAutoCorrectionIndicatorOn(newAutoCorrectionIndicator); 178077d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard if (DEBUG) { 1781fe2d90798ea409ee39d6f63942eb01bb7eed98e3satok Log.d(TAG, "Flip the indicator. " + oldAutoCorrectionIndicator 1782fe2d90798ea409ee39d6f63942eb01bb7eed98e3satok + " -> " + newAutoCorrectionIndicator); 17830bfe359ee42af9c4487ce56acf42c74a2510980dJean Chalard if (mComposingStateManager.isComposing() && newAutoCorrectionIndicator 178477d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard != mComposingStateManager.isAutoCorrectionIndicatorOn()) { 17850bfe359ee42af9c4487ce56acf42c74a2510980dJean Chalard throw new RuntimeException("Couldn't flip the indicator!"); 178677d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard } 1787fe2d90798ea409ee39d6f63942eb01bb7eed98e3satok } 178877d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard final CharSequence textWithUnderline = 178977d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard getTextWithUnderline(mWordComposer.getTypedWord()); 1790604d80c67185954d4691ac775be59c499eee3b1csatok if (!TextUtils.isEmpty(textWithUnderline)) { 1791604d80c67185954d4691ac775be59c499eee3b1csatok ic.setComposingText(textWithUnderline, 1); 1792604d80c67185954d4691ac775be59c499eee3b1csatok } 1793ec780e2868962bf17f0dfd35d36895f543bde40asatok } 1794ec780e2868962bf17f0dfd35d36895f543bde40asatok } 1795466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1796466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1797409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void updateSuggestions() { 1798923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Check if we have a suggestion engine attached. 17999fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if ((mSuggest == null || !isSuggestionsRequested()) 1800b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok && !mVoiceProxy.isVoiceInputHighlighted()) { 1801edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard if (mWordComposer.isComposingWord()) { 1802edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard Log.w(TAG, "Called updateSuggestions but suggestions were not requested!"); 1803edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard mWordComposer.setAutoCorrection(mWordComposer.getTypedWord()); 1804edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard } 1805923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1806923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1807466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1808cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard mHandler.cancelUpdateSuggestions(); 1809cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard mHandler.cancelUpdateBigramPredictions(); 1810cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard 1811196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (!mWordComposer.isComposingWord()) { 1812ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setPunctuationSuggestions(); 1813923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1814923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1815979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 18169f67e12a0e3f77985fb8bafe0db4c00e32317b9asatok // TODO: May need a better way of retrieving previous word 181740f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final InputConnection ic = getCurrentInputConnection(); 181840f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final CharSequence prevWord; 181940f7efc172928bdd6048e91421a766abe5b22996Jean Chalard if (null == ic) { 182040f7efc172928bdd6048e91421a766abe5b22996Jean Chalard prevWord = null; 182140f7efc172928bdd6048e91421a766abe5b22996Jean Chalard } else { 182240f7efc172928bdd6048e91421a766abe5b22996Jean Chalard prevWord = EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators); 182340f7efc172928bdd6048e91421a766abe5b22996Jean Chalard } 182440f7efc172928bdd6048e91421a766abe5b22996Jean Chalard // getSuggestedWordBuilder handles gracefully a null value of prevWord 1825f7d6517d6b1a1dd88e2142e1a15703bb839be01bJean Chalard final SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(mWordComposer, 18263708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(), mCorrectionMode); 1827923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1828dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard boolean autoCorrectionAvailable = !mInputAttributes.mInputTypeNoAutoCorrect 1829dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard && mSuggest.hasAutoCorrection(); 1830f7d6517d6b1a1dd88e2142e1a15703bb839be01bJean Chalard final CharSequence typedWord = mWordComposer.getTypedWord(); 1831bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // Here, we want to promote a whitelisted word if exists. 18325f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard // TODO: Change this scheme - a boolean is not enough. A whitelisted word may be "valid" 18335f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard // but still autocorrected from - in the case the whitelist only capitalizes the word. 18345f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard // The whitelist should be case-insensitive, so it's not possible to be consistent with 18355f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard // a boolean flag. Right now this is handled with a slight hack in 18365f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard // WhitelistDictionary#shouldForciblyAutoCorrectFrom. 1837f7d6517d6b1a1dd88e2142e1a15703bb839be01bJean Chalard final int quotesCount = mWordComposer.trailingSingleQuotesCount(); 18385f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard final boolean allowsToBeAutoCorrected = AutoCorrection.allowsToBeAutoCorrected( 1839c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard mSuggest.getUnigramDictionaries(), 1840c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard // If the typed string ends with a single quote, for dictionary lookup purposes 1841c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard // we behave as if the single quote was not here. Here, we are looking up the 1842c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard // typed string in the dictionary (to avoid autocorrecting from an existing 1843c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard // word, so for consistency this lookup should be made WITHOUT the trailing 1844c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard // single quote. 1845117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard quotesCount > 0 1846117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard ? typedWord.subSequence(0, typedWord.length() - quotesCount) : typedWord, 1847c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard preferCapitalization()); 1848979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mCorrectionMode == Suggest.CORRECTION_FULL 1849979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { 18505f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard autoCorrectionAvailable |= (!allowsToBeAutoCorrected); 1851923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 18524a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani // Don't auto-correct words with multiple capital letter 1853f7d6517d6b1a1dd88e2142e1a15703bb839be01bJean Chalard autoCorrectionAvailable &= !mWordComposer.isMostlyCaps(); 1854979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1855a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // Basically, we update the suggestion strip only when suggestion count > 1. However, 1856a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // there is an exception: We update the suggestion strip whenever typed word's length 1857f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // is 1 or typed word is found in dictionary, regardless of suggestion count. Actually, 1858f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // in most cases, suggestion count is 1 when typed word's length is 1, but we do always 1859f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // need to clear the previous state when the user starts typing a word (i.e. typed word's 1860f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // length == 1). 1861fe1a6d961cf039357f061482461e4d2e951ad346satok if (typedWord != null) { 18625f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard if (builder.size() > 1 || typedWord.length() == 1 || (!allowsToBeAutoCorrected) 1863913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka || mSuggestionsView.isShowingAddToDictionaryHint()) { 18645f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard builder.setTypedWordValid(!allowsToBeAutoCorrected).setHasMinimalSuggestion( 18658558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa autoCorrectionAvailable); 1866fe1a6d961cf039357f061482461e4d2e951ad346satok } else { 1867074cda4d266b5d034d4348961c9183e32b16af5asatok SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions(); 1868074cda4d266b5d034d4348961c9183e32b16af5asatok if (previousSuggestions == mSettingsValues.mSuggestPuncList) { 1869074cda4d266b5d034d4348961c9183e32b16af5asatok if (builder.size() == 0) { 1870074cda4d266b5d034d4348961c9183e32b16af5asatok return; 1871074cda4d266b5d034d4348961c9183e32b16af5asatok } 1872074cda4d266b5d034d4348961c9183e32b16af5asatok previousSuggestions = SuggestedWords.EMPTY; 1873074cda4d266b5d034d4348961c9183e32b16af5asatok } 1874fe1a6d961cf039357f061482461e4d2e951ad346satok builder.addTypedWordAndPreviousSuggestions(typedWord, previousSuggestions); 1875fe1a6d961cf039357f061482461e4d2e951ad346satok } 18769fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka } 18777e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka showSuggestions(builder.build(), typedWord); 1878979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 18794a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani 18809fbfd5877305ed19a20663630b498b6b3fdae942satok public void showSuggestions(SuggestedWords suggestedWords, CharSequence typedWord) { 18812aa1dd45c44295e2f7e8ece1b520032d86b9f908satok final boolean shouldBlockAutoCorrectionBySafetyNet = 18822aa1dd45c44295e2f7e8ece1b520032d86b9f908satok Utils.shouldBlockAutoCorrectionBySafetyNet(suggestedWords, mSuggest); 18832aa1dd45c44295e2f7e8ece1b520032d86b9f908satok if (shouldBlockAutoCorrectionBySafetyNet) { 18842aa1dd45c44295e2f7e8ece1b520032d86b9f908satok suggestedWords.setShouldBlockAutoCorrection(); 18852aa1dd45c44295e2f7e8ece1b520032d86b9f908satok } 18867e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(suggestedWords); 18877e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka if (suggestedWords.size() > 0) { 18882aa1dd45c44295e2f7e8ece1b520032d86b9f908satok if (shouldBlockAutoCorrectionBySafetyNet) { 1889117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard mWordComposer.setAutoCorrection(typedWord); 189082411d47ba7e8133ed2390c6920945e139a738cesatok } else if (suggestedWords.hasAutoCorrectionWord()) { 1891117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard mWordComposer.setAutoCorrection(suggestedWords.getWord(1)); 1892923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1893117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard mWordComposer.setAutoCorrection(typedWord); 1894923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1895923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1896117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard // TODO: replace with mWordComposer.deleteAutoCorrection()? 1897117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard mWordComposer.setAutoCorrection(null); 1898923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1899913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShown(isSuggestionsStripVisible()); 1900923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1901923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1902f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard private void commitCurrentAutoCorrection(final int separatorCodePoint, 1903f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard final InputConnection ic) { 1904913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka // Complete any pending suggestions query first 1905d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka if (mHandler.hasPendingUpdateSuggestions()) { 1906d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 1907923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 1908923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1909117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard final CharSequence autoCorrection = mWordComposer.getAutoCorrectionOrNull(); 1910117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard if (autoCorrection != null) { 1911117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard final String typedWord = mWordComposer.getTypedWord(); 191246798d8f1f3d9012433d000790ba30ba910c0fa0Jean Chalard if (TextUtils.isEmpty(typedWord)) { 191346798d8f1f3d9012433d000790ba30ba910c0fa0Jean Chalard throw new RuntimeException("We have an auto-correction but the typed word " 191446798d8f1f3d9012433d000790ba30ba910c0fa0Jean Chalard + "is empty? Impossible! I must commit suicide."); 191546798d8f1f3d9012433d000790ba30ba910c0fa0Jean Chalard } 1916f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard Utils.Stats.onAutoCorrection(typedWord, autoCorrection.toString(), separatorCodePoint); 19174733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 191866bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitChosenWord(autoCorrection, LastComposedWord.COMMIT_TYPE_DECIDED_WORD, 191966bb563535dbe3672f99f75bd71763a551444867Jean Chalard separatorCodePoint); 1920f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard // Add the word to the user unigram dictionary if it's not a known word 1921117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard addToUserUnigramAndBigramDictionaries(autoCorrection, 1922f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard UserUnigramDictionary.FREQUENCY_FOR_TYPED); 1923f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard if (!typedWord.equals(autoCorrection) && null != ic) { 19241c6cf26c3705e845418a29718c034598b52293ccJean Chalard // This will make the correction flash for a short while as a visual clue 19251c6cf26c3705e845418a29718c034598b52293ccJean Chalard // to the user that auto-correction happened. 19261c6cf26c3705e845418a29718c034598b52293ccJean Chalard InputConnectionCompatUtils.commitCorrection(ic, 19271c6cf26c3705e845418a29718c034598b52293ccJean Chalard mLastSelectionEnd - typedWord.length(), typedWord, autoCorrection); 19281c6cf26c3705e845418a29718c034598b52293ccJean Chalard } 1929923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1930923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1931923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1932c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka @Override 19332e2d6b4d4060ed3b956b4bd4c1f89b5d9c87b525Jean Chalard public void pickSuggestionManually(final int index, final CharSequence suggestion) { 1934604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.onFinishComposingText(); 19352e2d6b4d4060ed3b956b4bd4c1f89b5d9c87b525Jean Chalard final SuggestedWords suggestions = mSuggestionsView.getSuggestions(); 193617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mVoiceProxy.flushAndLogAllTextModificationCounters(index, suggestion, 193717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mWordSeparators); 19384f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1939dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard if (mInputAttributes.mApplicationSpecifiedCompletionOn 1940dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard && mApplicationSpecifiedCompletions != null 19411b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka && index >= 0 && index < mApplicationSpecifiedCompletions.length) { 1942913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) { 1943913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.clear(); 1944923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1945b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1946e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard final InputConnection ic = getCurrentInputConnection(); 19479a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 1948e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard ic.beginBatchEdit(); 1949e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index]; 1950e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard ic.commitCompletion(completionInfo); 19519a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 19529a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1953923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1954923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 19556a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 1956e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard // If this is a punctuation picked from the suggestion strip, pass it to onCodeInput 1957e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard if (suggestion.length() == 1 && isShowingPunctuationList()) { 1958979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Word separators are suggested before the user inputs something. 1959979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // So, LatinImeLogger logs "" as a user's input. 1960979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.logOnManualSuggestion( 19617e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka "", suggestion.toString(), index, suggestions.mWords); 1962e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard // Rely on onCodeInput to do the complicated swapping/stripping logic consistently. 19632e2d6b4d4060ed3b956b4bd4c1f89b5d9c87b525Jean Chalard final int primaryCode = suggestion.charAt(0); 1964e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard onCodeInput(primaryCode, new int[] { primaryCode }, 1965e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard KeyboardActionListener.SUGGESTION_STRIP_COORDINATE, 1966e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard KeyboardActionListener.SUGGESTION_STRIP_COORDINATE); 19676a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani return; 19686a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 1969af9fe5c5fcad1db22f605e0568c9a77cef178d22Jean Chalard // We need to log before we commit, because the word composer will store away the user 1970af9fe5c5fcad1db22f605e0568c9a77cef178d22Jean Chalard // typed word. 1971af9fe5c5fcad1db22f605e0568c9a77cef178d22Jean Chalard LatinImeLogger.logOnManualSuggestion(mWordComposer.getTypedWord().toString(), 1972af9fe5c5fcad1db22f605e0568c9a77cef178d22Jean Chalard suggestion.toString(), index, suggestions.mWords); 19734733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 197466bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitChosenWord(suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK, 197566bb563535dbe3672f99f75bd71763a551444867Jean Chalard LastComposedWord.NOT_A_SEPARATOR); 19769468335a06d2b0e3ef15f4f57f8c1b0857b34ebeAmith Yamasani // Add the word to the auto dictionary if it's not a known word 19770c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani if (index == 0) { 1978f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard addToUserUnigramAndBigramDictionaries(suggestion, 1979f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard UserUnigramDictionary.FREQUENCY_FOR_PICKED); 1980979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 1981bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok addToOnlyBigramDictionary(suggestion, 1); 19820c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani } 1983fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard mSpaceState = SPACE_STATE_PHANTOM; 1984fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // TODO: is this necessary? 1985fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard mKeyboardSwitcher.updateShiftState(); 1986979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1987c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // We should show the "Touch again to save" hint if the user pressed the first entry 1988c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // AND either: 19897f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is no dictionary (we know that because we tried to load it => null != mSuggest 1990c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // AND mSuggest.hasMainDictionary() is false) 19917f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is a dictionary and the word is not in it 19927f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // Please note that if mSuggest is null, it means that everything is off: suggestion 19937f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // and correction, so we shouldn't try to show the hint 19947f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // We used to look at mCorrectionMode here, but showing the hint should have nothing 19957f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // to do with the autocorrection setting. 1996bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean showingAddToDictionaryHint = index == 0 && mSuggest != null 1997bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // If there is no dictionary the hint should be shown. 1998c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa && (!mSuggest.hasMainDictionary() 1999bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // If "suggestion" is not in the dictionary, the hint should be shown. 2000bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok || !AutoCorrection.isValidWord( 2001bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok mSuggest.getUnigramDictionaries(), suggestion, true)); 2002b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani 2003406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard Utils.Stats.onSeparator((char)Keyboard.CODE_SPACE, WordComposer.NOT_A_COORDINATE, 2004406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard WordComposer.NOT_A_COORDINATE); 2005777118a40a363ccab69a00016d3156066513cb78Jean Chalard if (!showingAddToDictionaryHint) { 2006364da8c618303a7764595d2c15ee034a7671365dKen Wakasa // If we're not showing the "Touch again to save", then show corrections again. 2007979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // In case the cursor position doesn't change, make sure we show the suggestions again. 200841ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard updateBigramPredictions(); 200941ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // Updating the predictions right away may be slow and feel unresponsive on slower 201041ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // terminals. On the other hand if we just postUpdateBigramPredictions() it will 201141ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // take a noticeable delay to update them which may feel uneasy. 201295a6e58ebcd8f44b970a8238cf30e48b10fc4b61Jean Chalard } else { 201388562bec54658840dcce352127bdc15705c20a89Jean Chalard if (mIsUserDictionaryAvailable) { 2014644d33d60ea5a87501274488013d65f55238895eKen Wakasa mSuggestionsView.showAddToDictionaryHint( 2015644d33d60ea5a87501274488013d65f55238895eKen Wakasa suggestion, mSettingsValues.mHintToSaveText); 2016ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka } else { 2017ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 2018ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka } 201966a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani } 2020923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2021a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2022979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 20238558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa * Commits the chosen word to the text field and saves it for later retrieval. 2024979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 202566bb563535dbe3672f99f75bd71763a551444867Jean Chalard private void commitChosenWord(final CharSequence bestWord, final int commitType, 202666bb563535dbe3672f99f75bd71763a551444867Jean Chalard final int separatorCode) { 20279351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 2028923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 20291fef530ec7626fa16777f52b48191e61db8f46d4satok mVoiceProxy.rememberReplacedWord(bestWord, mSettingsValues.mWordSeparators); 20301531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard if (mSettingsValues.mEnableSuggestionSpanInsertion) { 20311531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions(); 20321531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan( 20331531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard this, bestWord, suggestedWords), 1); 20341531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard } else { 20351531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard ic.commitText(bestWord, 1); 20361531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard } 2037923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 20380fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard // TODO: figure out here if this is an auto-correct or if the best word is actually 20390fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard // what user typed. Note: currently this is done much later in 2040b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard // LastComposedWord#canCancelAutoCorrect by string equality of the remembered 20410fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard // strings. 204266bb563535dbe3672f99f75bd71763a551444867Jean Chalard mLastComposedWord = mWordComposer.commitWord(commitType, bestWord.toString(), 204366bb563535dbe3672f99f75bd71763a551444867Jean Chalard separatorCode); 2044923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2045923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 204689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard private static final WordComposer sEmptyWordComposer = new WordComposer(); 204741ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard public void updateBigramPredictions() { 204889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (mSuggest == null || !isSuggestionsRequested()) 204989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard return; 205089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 205117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (!mSettingsValues.mBigramPredictionEnabled) { 2052cb3320179d39a7983874697a0aa428b127675c9dJean Chalard setPunctuationSuggestions(); 2053cb3320179d39a7983874697a0aa428b127675c9dJean Chalard return; 2054cb3320179d39a7983874697a0aa428b127675c9dJean Chalard } 2055cb3320179d39a7983874697a0aa428b127675c9dJean Chalard 205689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(), 205717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mWordSeparators); 2058904baab25a4c6ec5d9c4bf7e562154e3f544d296satok SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(sEmptyWordComposer, 20593708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(), mCorrectionMode); 206089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 206189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (builder.size() > 0) { 206289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Explicitly supply an empty typed word (the no-second-arg version of 206389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // showSuggestions will retrieve the word near the cursor, we don't want that here) 206489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard showSuggestions(builder.build(), ""); 206589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 206689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (!isShowingPunctuationList()) setPunctuationSuggestions(); 206789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 206889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 206989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 20707a8dac55278cedd838be325f56b4c52d973c61f5satok public void setPunctuationSuggestions() { 207117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard setSuggestions(mSettingsValues.mSuggestPuncList); 2072913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShown(isSuggestionsStripVisible()); 20736a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 20746a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 2075f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard private void addToUserUnigramAndBigramDictionaries(CharSequence suggestion, 2076f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard int frequencyDelta) { 2077979f8690967ff5409fe18f5085858ccdb8e0ccf1satok checkAddToDictionary(suggestion, frequencyDelta, false); 2078979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2079979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2080bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok private void addToOnlyBigramDictionary(CharSequence suggestion, int frequencyDelta) { 2081979f8690967ff5409fe18f5085858ccdb8e0ccf1satok checkAddToDictionary(suggestion, frequencyDelta, true); 2082979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2083979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2084979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 2085f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard * Adds to the UserBigramDictionary and/or UserUnigramDictionary 2086bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok * @param selectedANotTypedWord true if it should be added to bigram dictionary if possible 2087979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 2088979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void checkAddToDictionary(CharSequence suggestion, int frequencyDelta, 2089bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok boolean selectedANotTypedWord) { 2090979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (suggestion == null || suggestion.length() < 1) return; 2091bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok 20920c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be 20930c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // adding words in situations where the user or application really didn't 20940c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // want corrections enabled or learned. 2095979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (!(mCorrectionMode == Suggest.CORRECTION_FULL 2096979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) { 2097979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return; 2098979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2099bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok 21005955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard if (null != mSuggest && null != mUserUnigramDictionary) { 21015955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard final boolean selectedATypedWordAndItsInUserUnigramDic = 21025955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard !selectedANotTypedWord && mUserUnigramDictionary.isValidWord(suggestion); 21035955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard final boolean isValidWord = AutoCorrection.isValidWord( 21045955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard mSuggest.getUnigramDictionaries(), suggestion, true); 21055955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard final boolean needsToAddToUserUnigramDictionary = 21065955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard selectedATypedWordAndItsInUserUnigramDic || !isValidWord; 21075955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard if (needsToAddToUserUnigramDictionary) { 21085955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard mUserUnigramDictionary.addWord(suggestion.toString(), frequencyDelta); 21095955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard } 2110e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 2111979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2112e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mUserBigramDictionary != null) { 2113863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // We don't want to register as bigrams words separated by a separator. 2114863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // For example "I will, and you too" : we don't want the pair ("will" "and") to be 2115863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // a bigram. 211640f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final InputConnection ic = getCurrentInputConnection(); 211740f7efc172928bdd6048e91421a766abe5b22996Jean Chalard if (null != ic) { 211840f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final CharSequence prevWord = 211940f7efc172928bdd6048e91421a766abe5b22996Jean Chalard EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators); 212040f7efc172928bdd6048e91421a766abe5b22996Jean Chalard if (!TextUtils.isEmpty(prevWord)) { 212140f7efc172928bdd6048e91421a766abe5b22996Jean Chalard mUserBigramDictionary.addBigrams(prevWord.toString(), suggestion.toString()); 212240f7efc172928bdd6048e91421a766abe5b22996Jean Chalard } 2123979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 212432e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 212532e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 212632e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani 21277a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isCursorTouchingWord() { 21289351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 2129923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return false; 2130923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toLeft = ic.getTextBeforeCursor(1, 0); 2131923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toRight = ic.getTextAfterCursor(1, 0); 2132923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!TextUtils.isEmpty(toLeft) 21336a800b253f0ea329808b582033a0ec3fc240d692Jean Chalard && !mSettingsValues.isWordSeparator(toLeft.charAt(0))) { 2134923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 2135923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2136a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker if (!TextUtils.isEmpty(toRight) 21376a800b253f0ea329808b582033a0ec3fc240d692Jean Chalard && !mSettingsValues.isWordSeparator(toRight.charAt(0))) { 2138923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 2139923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2140923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 2141923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2142a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2143120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // "ic" must not be null 21448ff0564f6a7c78e2fda517ea49b2ac2fa96d0f8eJean Chalard private static boolean sameAsTextBeforeCursor(final InputConnection ic, 21458ff0564f6a7c78e2fda517ea49b2ac2fa96d0f8eJean Chalard final CharSequence text) { 21468ff0564f6a7c78e2fda517ea49b2ac2fa96d0f8eJean Chalard final CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0); 2147dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani return TextUtils.equals(text, beforeText); 2148dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani } 2149dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 2150120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // "ic" must not be null 21516b1f500da451de56932a8b2a99c63857994ece85Jean Chalard /** 21526b1f500da451de56932a8b2a99c63857994ece85Jean Chalard * Check if the cursor is actually at the end of a word. If so, restart suggestions on this 21536b1f500da451de56932a8b2a99c63857994ece85Jean Chalard * word, else do nothing. 21546b1f500da451de56932a8b2a99c63857994ece85Jean Chalard */ 21556b1f500da451de56932a8b2a99c63857994ece85Jean Chalard private void restartSuggestionsOnWordBeforeCursorIfAtEndOfWord( 21566b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final InputConnection ic) { 21576b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Bail out if the cursor is not at the end of a word (cursor must be preceded by 21586b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // non-whitespace, non-separator, non-start-of-text) 21596b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Example ("|" is the cursor here) : <SOL>"|a" " |a" " | " all get rejected here. 21606b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final CharSequence textBeforeCursor = ic.getTextBeforeCursor(1, 0); 21616b1f500da451de56932a8b2a99c63857994ece85Jean Chalard if (TextUtils.isEmpty(textBeforeCursor) 21626b1f500da451de56932a8b2a99c63857994ece85Jean Chalard || mSettingsValues.isWordSeparator(textBeforeCursor.charAt(0))) return; 21636b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 21646b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Bail out if the cursor is in the middle of a word (cursor must be followed by whitespace, 21656b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // separator or end of line/text) 21666b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Example: "test|"<EOL> "te|st" get rejected here 21676b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final CharSequence textAfterCursor = ic.getTextAfterCursor(1, 0); 21686b1f500da451de56932a8b2a99c63857994ece85Jean Chalard if (!TextUtils.isEmpty(textAfterCursor) 21696b1f500da451de56932a8b2a99c63857994ece85Jean Chalard && !mSettingsValues.isWordSeparator(textAfterCursor.charAt(0))) return; 21706b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 21716b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Bail out if word before cursor is 0-length or a single non letter (like an apostrophe) 2172fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // Example: " -|" gets rejected here but "e-|" and "e|" are okay 2173fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard CharSequence word = EditingUtils.getWordAtCursor(ic, mSettingsValues.mWordSeparators); 2174fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // We don't suggest on leading single quotes, so we have to remove them from the word if 2175fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // it starts with single quotes. 2176fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard while (!TextUtils.isEmpty(word) && Keyboard.CODE_SINGLE_QUOTE == word.charAt(0)) { 2177fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard word = word.subSequence(1, word.length()); 2178fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard } 21796b1f500da451de56932a8b2a99c63857994ece85Jean Chalard if (TextUtils.isEmpty(word)) return; 2180fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard final char firstChar = word.charAt(0); // we just tested that word is not empty 2181fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard if (word.length() == 1 && !Character.isLetter(firstChar)) return; 2182fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard 2183fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // We only suggest on words that start with a letter or a symbol that is excluded from 2184fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // word separators (see #handleCharacterWhileInBatchEdit). 2185fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard if (!(isAlphabet(firstChar) 2186fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard || mSettingsValues.isSymbolExcludedFromWordSeparators(firstChar))) { 2187fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard return; 2188fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard } 21896b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 21906b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Okay, we are at the end of a word. Restart suggestions. 21916b1f500da451de56932a8b2a99c63857994ece85Jean Chalard restartSuggestionsOnWordBeforeCursor(ic, word); 21926b1f500da451de56932a8b2a99c63857994ece85Jean Chalard } 21936b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 21946b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // "ic" must not be null 21956b1f500da451de56932a8b2a99c63857994ece85Jean Chalard private void restartSuggestionsOnWordBeforeCursor(final InputConnection ic, 21966b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final CharSequence word) { 21973708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka mWordComposer.setComposingWord(word, mKeyboardSwitcher.getKeyboard()); 21986b1f500da451de56932a8b2a99c63857994ece85Jean Chalard mComposingStateManager.onStartComposingText(); 21996b1f500da451de56932a8b2a99c63857994ece85Jean Chalard ic.deleteSurroundingText(word.length(), 0); 22006b1f500da451de56932a8b2a99c63857994ece85Jean Chalard ic.setComposingText(word, 1); 22016b1f500da451de56932a8b2a99c63857994ece85Jean Chalard mHandler.postUpdateSuggestions(); 22026b1f500da451de56932a8b2a99c63857994ece85Jean Chalard } 22036b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 22046b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // "ic" must not be null 2205890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard private void cancelAutoCorrect(final InputConnection ic) { 2206b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard final String originallyTypedWord = mLastComposedWord.mTypedWord; 2207cf9d92629cae88273805eaf7984fcfdd8afd11f5Jean Chalard final CharSequence committedWord = mLastComposedWord.mCommittedWord; 2208cf9d92629cae88273805eaf7984fcfdd8afd11f5Jean Chalard final int cancelLength = committedWord.length(); 2209193d23f40e1556074f323b7bd9695759f4798efeJean Chalard final int separatorLength = mLastComposedWord.getSeparatorLength( 2210193d23f40e1556074f323b7bd9695759f4798efeJean Chalard mLastComposedWord.mSeparatorCode); 2211193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // TODO: should we check our saved separator against the actual contents of the text view? 2212890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard if (DEBUG) { 2213b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard if (mWordComposer.isComposingWord()) { 2214b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard throw new RuntimeException("cancelAutoCorrect, but we are composing a word"); 2215b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard } 2216890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard final String wordBeforeCursor = 2217193d23f40e1556074f323b7bd9695759f4798efeJean Chalard ic.getTextBeforeCursor(cancelLength + separatorLength, 0) 2218193d23f40e1556074f323b7bd9695759f4798efeJean Chalard .subSequence(0, cancelLength).toString(); 2219cf9d92629cae88273805eaf7984fcfdd8afd11f5Jean Chalard if (!TextUtils.equals(committedWord, wordBeforeCursor)) { 2220890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard throw new RuntimeException("cancelAutoCorrect check failed: we thought we were " 2221cf9d92629cae88273805eaf7984fcfdd8afd11f5Jean Chalard + "reverting \"" + committedWord 2222890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard + "\", but before the cursor we found \"" + wordBeforeCursor + "\""); 2223890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard } 22247546ff6e34d540e9529d785bfc691b9c155b4051Jean Chalard if (TextUtils.equals(originallyTypedWord, wordBeforeCursor)) { 2225890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard throw new RuntimeException("cancelAutoCorrect check failed: we wanted to cancel " 22269e8761c4402ddc11c942ed2e583bd7d58f70c5eaJean Chalard + "auto correction and revert to \"" + originallyTypedWord 2227890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard + "\" but we found this very string before the cursor"); 2228890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard } 22298558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa } 2230193d23f40e1556074f323b7bd9695759f4798efeJean Chalard ic.deleteSurroundingText(cancelLength + separatorLength, 0); 2231193d23f40e1556074f323b7bd9695759f4798efeJean Chalard if (0 == separatorLength || mLastComposedWord.didCommitTypedWord()) { 2232193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // This is the case when we cancel a manual pick. 2233193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // We should restart suggestion on the word right away. 223432f0af1fc48f67907f0e731e18359f29e2b1df14Jean Chalard mWordComposer.resumeSuggestionOnLastComposedWord(mLastComposedWord); 223532f0af1fc48f67907f0e731e18359f29e2b1df14Jean Chalard mComposingStateManager.onStartComposingText(); 223632f0af1fc48f67907f0e731e18359f29e2b1df14Jean Chalard ic.setComposingText(originallyTypedWord, 1); 2237193d23f40e1556074f323b7bd9695759f4798efeJean Chalard } else { 2238193d23f40e1556074f323b7bd9695759f4798efeJean Chalard ic.commitText(originallyTypedWord, 1); 2239193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // Re-insert the separator 2240193d23f40e1556074f323b7bd9695759f4798efeJean Chalard sendKeyCodePoint(mLastComposedWord.mSeparatorCode); 2241193d23f40e1556074f323b7bd9695759f4798efeJean Chalard Utils.Stats.onSeparator(mLastComposedWord.mSeparatorCode, WordComposer.NOT_A_COORDINATE, 2242193d23f40e1556074f323b7bd9695759f4798efeJean Chalard WordComposer.NOT_A_COORDINATE); 2243193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // Don't restart suggestion yet. We'll restart if the user deletes the 2244193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // separator. 2245193d23f40e1556074f323b7bd9695759f4798efeJean Chalard } 2246b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; 2247890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard mHandler.cancelUpdateBigramPredictions(); 2248890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard mHandler.postUpdateSuggestions(); 2249890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard } 2250890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard 2251890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard // "ic" must not be null 2252890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard private void restartSuggestionsOnManuallyPickedTypedWord(final InputConnection ic) { 22533b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // Note: this relies on the last word still being held in the WordComposer, in 22543b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // the field for suggestion resuming. 22553b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // Note: in the interest of code simplicity, we may want to just call 22563b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // restartSuggestionsOnWordBeforeCursorIfAtEndOfWord instead, but retrieving 22573b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // the old WordComposer allows to reuse the actual typed coordinates. 22582712f23acbb197af3b125da4cc47108e71b7446dJean Chalard mWordComposer.resumeSuggestionOnLastComposedWord(mLastComposedWord); 22593b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // We resume suggestion, and then we want to set the composing text to the content 22603b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // of the word composer again. But since we just manually picked a word, there is 22613b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // no composing text at the moment, so we have to delete the word before we set a 22623b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // new composing text. 2263c2a76a1529870b59bba133a7d76a800cbd20ecfaJean Chalard final int restartLength = mWordComposer.size(); 2264890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard if (DEBUG) { 2265a7f2500001c53dc5a6de9c2525a75229cc7c6645Jean Chalard final String wordBeforeCursor = ic.getTextBeforeCursor(restartLength, 0).toString(); 22667546ff6e34d540e9529d785bfc691b9c155b4051Jean Chalard if (!TextUtils.equals(mWordComposer.getTypedWord(), wordBeforeCursor)) { 2267890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard throw new RuntimeException("restartSuggestionsOnManuallyPickedTypedWord " 2268890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard + "check failed: we thought we were reverting \"" 2269890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard + mWordComposer.getTypedWord() 2270890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard + "\", but before the cursor we found \"" 2271890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard + wordBeforeCursor + "\""); 2272890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard } 2273923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2274a7f2500001c53dc5a6de9c2525a75229cc7c6645Jean Chalard ic.deleteSurroundingText(restartLength, 0); 2275172a013ab5481dee22e0637bc997b8bcbc4436dbJean Chalard mComposingStateManager.onStartComposingText(); 2276890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard ic.setComposingText(mWordComposer.getTypedWord(), 1); 22778558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa mHandler.cancelUpdateBigramPredictions(); 22788558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa mHandler.postUpdateSuggestions(); 2279923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2280923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2281120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // "ic" must not be null 22822124bc5bf5af31cf3d2789b70ebd2f24c815f5f4Jean Chalard private boolean revertDoubleSpaceWhileInBatchEdit(final InputConnection ic) { 22834733609947c0ec74e460bd714fffca0518ade93aJean Chalard mHandler.cancelDoubleSpacesTimer(); 22844733609947c0ec74e460bd714fffca0518ade93aJean Chalard // Here we test whether we indeed have a period and a space before us. This should not 22854733609947c0ec74e460bd714fffca0518ade93aJean Chalard // be needed, but it's there just in case something went wrong. 22864733609947c0ec74e460bd714fffca0518ade93aJean Chalard final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0); 22878ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard if (!". ".equals(textBeforeCursor)) { 228851fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard // Theoretically we should not be coming here if there isn't ". " before the 228951fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard // cursor, but the application may be changing the text while we are typing, so 229051fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard // anything goes. We should not crash. 229151fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard Log.d(TAG, "Tried to revert double-space combo but we didn't find " 22928ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard + "\". \" just before the cursor."); 229351fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard return false; 22948ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard } 22954733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.deleteSurroundingText(2, 0); 22964733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.commitText(" ", 1); 22974733609947c0ec74e460bd714fffca0518ade93aJean Chalard return true; 22984733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 22994733609947c0ec74e460bd714fffca0518ade93aJean Chalard 23008fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka private static boolean revertSwapPunctuation(final InputConnection ic) { 2301120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Here we test whether we indeed have a space and something else before us. This should not 2302120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // be needed, but it's there just in case something went wrong. 2303120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0); 2304120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // NOTE: This does not work with surrogate pairs. Hopefully when the keyboard is able to 2305120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // enter surrogate pairs this code will have been removed. 23068be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard if (TextUtils.isEmpty(textBeforeCursor) 23078be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard || (Keyboard.CODE_SPACE != textBeforeCursor.charAt(1))) { 23088be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard // We may only come here if the application is changing the text while we are typing. 23098be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard // This is quite a broken case, but not logically impossible, so we shouldn't crash, 23108be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard // but some debugging log may be in order. 23118be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard Log.d(TAG, "Tried to revert a swap of punctuation but we didn't " 23128ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard + "find a space just before the cursor."); 23138be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard return false; 23148ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard } 2315120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.beginBatchEdit(); 2316120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.deleteSurroundingText(2, 0); 2317120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.commitText(" " + textBeforeCursor.subSequence(0, 1), 1); 2318120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.endBatchEdit(); 2319120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return true; 2320120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 2321120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 2322923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean isWordSeparator(int code) { 232317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard return mSettingsValues.isWordSeparator(code); 2324923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2325923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2326923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean preferCapitalization() { 23279318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa return mWordComposer.isFirstCharCapitalized(); 2328923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2329923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 233088fc9d44186120f9edc5cf7ec0e2af85260fed04satok // Notify that language or mode have been changed and toggleLanguage will update KeyboardID 2331c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // according to new language or mode. 2332c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka public void onRefreshKeyboard() { 233355303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) { 233455303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka // Before Honeycomb, Voice IME is in LatinIME and it changes the current input view, 233555303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka // so that we need to re-create the keyboard input view here. 233655303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka setInputView(mKeyboardSwitcher.onCreateInputView()); 233755303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka } 23381e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka // When the device locale is changed in SetupWizard etc., this method may get called via 23391e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka // onConfigurationChanged before SoftInputWindow is shown. 23401e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka if (mKeyboardSwitcher.getKeyboardView() != null) { 23411e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka // Reload keyboard because the current language has been changed. 23421e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettingsValues); 23431e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka } 23440ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 234517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 234636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 234736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 2348a5c96f376ad57e78a88942bb618e067054ed818aTadashi G. Takaoka public void hapticAndAudioFeedback(int primaryCode) { 2349d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka vibrate(); 2350d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka playKeyClick(primaryCode); 2351d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka } 2352d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka 23535a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 23542a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka public void onPressKey(int primaryCode) { 2355a5c96f376ad57e78a88942bb618e067054ed818aTadashi G. Takaoka mKeyboardSwitcher.onPressKey(primaryCode); 2356923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2357923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 23585a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 23592a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka public void onReleaseKey(int primaryCode, boolean withSliding) { 23602a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka mKeyboardSwitcher.onReleaseKey(primaryCode, withSliding); 23618d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv 23628d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv // If accessibility is on, ensure the user receives keyboard state updates. 23638d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) { 23648d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv switch (primaryCode) { 23658d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case Keyboard.CODE_SHIFT: 23668d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv AccessibleKeyboardViewProxy.getInstance().notifyShiftState(); 23678d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv break; 23688d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: 23698d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv AccessibleKeyboardViewProxy.getInstance().notifySymbolsState(); 23708d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv break; 23718d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv } 23728d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv } 2373923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2374a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2375123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka // receive ringer mode change and network state change. 2376923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private BroadcastReceiver mReceiver = new BroadcastReceiver() { 2377923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 2378923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onReceive(Context context, Intent intent) { 2379123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final String action = intent.getAction(); 2380123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { 2381123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka updateRingerMode(); 2382123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 2383123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka mSubtypeSwitcher.onNetworkStateChanged(intent); 2384123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } 2385923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2386923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project }; 2387923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2388923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // update flags for silent mode 2389923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void updateRingerMode() { 2390923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 2391923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 2392bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa if (mAudioManager == null) return; 2393923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2394bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa mSilentModeOn = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL); 2395923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2396923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2397923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void playKeyClick(int primaryCode) { 2398923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // if mAudioManager is null, we don't have the ringer state yet 2399923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // mAudioManager will be set by updateRingerMode 2400923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 2401c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka if (mKeyboardSwitcher.getKeyboardView() != null) { 2402923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateRingerMode(); 2403923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2404923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 240517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (isSoundOn()) { 2406f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa final int sound; 2407923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 2408f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa case Keyboard.CODE_DELETE: 2409f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa sound = AudioManager.FX_KEYPRESS_DELETE; 2410f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa break; 2411f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa case Keyboard.CODE_ENTER: 2412f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa sound = AudioManager.FX_KEYPRESS_RETURN; 2413f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa break; 2414f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa case Keyboard.CODE_SPACE: 2415f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa sound = AudioManager.FX_KEYPRESS_SPACEBAR; 2416f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa break; 2417f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa default: 2418f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa sound = AudioManager.FX_KEYPRESS_STANDARD; 2419f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa break; 2420923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2421c207e0a7dad0bdae054be47cafe878698f9401fcJean Chalard mAudioManager.playSoundEffect(sound, mSettingsValues.mFxVolume); 2422923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2423923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2424923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2425409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void vibrate() { 242617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (!mSettingsValues.mVibrateOn) { 2427923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 2428923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2429c207e0a7dad0bdae054be47cafe878698f9401fcJean Chalard if (mSettingsValues.mKeypressVibrationDuration < 0) { 243028f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa // Go ahead with the system default 243128f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 243228f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa if (inputView != null) { 243328f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa inputView.performHapticFeedback( 243428f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa HapticFeedbackConstants.KEYBOARD_TAP, 243528f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); 243628f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa } 243728f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa } else if (mVibrator != null) { 2438c207e0a7dad0bdae054be47cafe878698f9401fcJean Chalard mVibrator.vibrate(mSettingsValues.mKeypressVibrationDuration); 2439923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2440923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2441923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2442f7d6517d6b1a1dd88e2142e1a15703bb839be01bJean Chalard public boolean isAutoCapitalized() { 2443f7d6517d6b1a1dd88e2142e1a15703bb839be01bJean Chalard return mWordComposer.isAutoCapitalized(); 24446516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani } 24456516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani 244617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard boolean isSoundOn() { 244717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard return mSettingsValues.mSoundOn && !mSilentModeOn; 2448979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2449979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2450e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private void updateCorrectionMode() { 24519f67e12a0e3f77985fb8bafe0db4c00e32317b9asatok // TODO: cleanup messy flags 2452f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled 2453dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard && !mInputAttributes.mInputTypeNoAutoCorrect; 2454283b0c2b642030539ba3e41f3f54b6aed6bb9e2dJean Chalard mCorrectionMode = shouldAutoCorrect ? Suggest.CORRECTION_FULL : Suggest.CORRECTION_NONE; 2455283b0c2b642030539ba3e41f3f54b6aed6bb9e2dJean Chalard mCorrectionMode = (mSettingsValues.mBigramSuggestionEnabled && shouldAutoCorrect) 2456979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ? Suggest.CORRECTION_FULL_BIGRAM : mCorrectionMode; 2457e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 2458e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani 24592ac5988f84b5c38d313951a3d7faddebf5f25e04Tadashi G. Takaoka private void updateSuggestionVisibility(final Resources res) { 24600fe3611bee5095e7bd0fff2d0fdf8d5a13379132Jean Chalard final String suggestionVisiblityStr = mSettingsValues.mShowSuggestionsSetting; 24617599cfea4a2d56f4779452ec8e8742f7b9629cc0satok for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) { 2462458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa if (suggestionVisiblityStr.equals(res.getString(visibility))) { 24637599cfea4a2d56f4779452ec8e8742f7b9629cc0satok mSuggestionVisibility = visibility; 24647599cfea4a2d56f4779452ec8e8742f7b9629cc0satok break; 24657599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 24667599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 24677599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 24687599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 2469466741d8a78965b8509bf527344f289e50873092Mike LeBeau protected void launchSettings() { 2470cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa launchSettingsClass(Settings.class); 2471466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 2472466741d8a78965b8509bf527344f289e50873092Mike LeBeau 2473bf96661d33d0126adb60a48880ceba1ff055d4a4satok public void launchDebugSettings() { 2474cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa launchSettingsClass(DebugSettings.class); 2475bf96661d33d0126adb60a48880ceba1ff055d4a4satok } 2476bf96661d33d0126adb60a48880ceba1ff055d4a4satok 2477cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa protected void launchSettingsClass(Class<? extends PreferenceActivity> settingsClass) { 2478923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project handleClose(); 2479923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Intent intent = new Intent(); 2480466741d8a78965b8509bf527344f289e50873092Mike LeBeau intent.setClass(LatinIME.this, settingsClass); 2481923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2482923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project startActivity(intent); 2483923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2484923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 24852fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showSubtypeSelectorAndSettings() { 248685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 248785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 248885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka // TODO: Should use new string "Select active input modes". 248985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.language_selection_title), 249085996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 249185996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 249285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 24932fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka @Override 24942fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka public void onClick(DialogInterface di, int position) { 24952fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka di.dismiss(); 24962fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka switch (position) { 249785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 24982cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok Intent intent = CompatUtils.getInputLanguageSelectionIntent( 24992a659b8aa642b0832fa0ac9a93e0640592fcc239Jean Chalard Utils.getInputMethodId(mImm, getPackageName()), 25002a659b8aa642b0832fa0ac9a93e0640592fcc239Jean Chalard Intent.FLAG_ACTIVITY_NEW_TASK 25012fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 25022fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_CLEAR_TOP); 25032fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka startActivity(intent); 25042fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2505aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa case 1: 2506aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa launchSettings(); 2507aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa break; 25082fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 25092fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 251085996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 2511bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka final AlertDialog.Builder builder = new AlertDialog.Builder(this) 2512bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setItems(items, listener) 2513bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setTitle(title); 2514bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka showOptionDialogInternal(builder.create()); 25152fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 2516923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 25172fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showOptionsMenu() { 251885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 251985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 252085996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.selectInputMethod), 252185996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 252285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 252385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 25245a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 2525923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onClick(DialogInterface di, int position) { 2526923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project di.dismiss(); 2527923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (position) { 252885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 2529ea55bf5df7d26d12b36c47141bfbac5730c3929aTadashi G. Takaoka mImm.showInputMethodPicker(); 25302fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 253185996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 1: 2532ea55bf5df7d26d12b36c47141bfbac5730c3929aTadashi G. Takaoka launchSettings(); 25332fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2534923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2535923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 253685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 2537bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka final AlertDialog.Builder builder = new AlertDialog.Builder(this) 2538bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setItems(items, listener) 2539bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setTitle(title); 2540bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka showOptionDialogInternal(builder.create()); 2541923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2542923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 25437e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 25447e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 2545923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.dump(fd, fout, args); 2546a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2547923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final Printer p = new PrintWriterPrinter(fout); 2548923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println("LatinIME state :"); 25493708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); 2550df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka final int keyboardMode = keyboard != null ? keyboard.mId.mMode : -1; 2551df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka p.println(" Keyboard mode = " + keyboardMode); 2552dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard p.println(" mIsSuggestionsRequested=" + mInputAttributes.mIsSettingsSuggestionStripOn); 2553923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mCorrectionMode=" + mCorrectionMode); 25544d0f03bd66742ee292da81a3e025e119f28b6940Jean Chalard p.println(" isComposingWord=" + mWordComposer.isComposingWord()); 255517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mAutoCorrectEnabled=" + mSettingsValues.mAutoCorrectEnabled); 255617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mSoundOn=" + mSettingsValues.mSoundOn); 255717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mVibrateOn=" + mSettingsValues.mVibrateOn); 2558240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard p.println(" mKeyPreviewPopupOn=" + mSettingsValues.mKeyPreviewPopupOn); 25596fa003ee234c6e2ca6cd9ec555221ac5c71a5405Jean Chalard p.println(" mInputAttributes=" + mInputAttributes.toString()); 2560923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2561923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 2562