LatinIME.java revision 8be16f78b10aa4a8975c4068db1b32f81f661a2c
1923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/* 2443c360d0afdbab091994244f045f4756feaf2b4Jean-Baptiste Queru * Copyright (C) 2008 The Android Open Source Project 3c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * 4923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * use this file except in compliance with the License. You may obtain a copy of 6923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License at 7a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker * 8923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker * 10923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * License for the specific language governing permissions and limitations under 14923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License. 15923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 16923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 17923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectpackage com.android.inputmethod.latin; 18923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 19923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.app.AlertDialog; 20923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.BroadcastReceiver; 21923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Context; 22923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.DialogInterface; 23923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Intent; 24923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.IntentFilter; 25923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.SharedPreferences; 26923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.res.Configuration; 2736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasaniimport android.content.res.Resources; 28923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.inputmethodservice.InputMethodService; 29923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.media.AudioManager; 30123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaokaimport android.net.ConnectivityManager; 31923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Debug; 32923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Message; 33923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.SystemClock; 34bf96661d33d0126adb60a48880ceba1ff055d4a4satokimport android.preference.PreferenceActivity; 35923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.preference.PreferenceManager; 36e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaokaimport android.text.InputType; 37923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.text.TextUtils; 38923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Log; 39923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.PrintWriterPrinter; 40923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Printer; 4166a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasaniimport android.view.HapticFeedbackConstants; 42923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.KeyEvent; 43923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.View; 448e09172df1bb176cc899940862c56bed9b9aec4esatokimport android.view.ViewGroup; 458e09172df1bb176cc899940862c56bed9b9aec4esatokimport android.view.ViewParent; 46923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.CompletionInfo; 47923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.EditorInfo; 48466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport android.view.inputmethod.ExtractedText; 49923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.InputConnection; 50c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka 515ac4638f999db4fea8a9e24171dbceb640a10858Alan Viveretteimport com.android.inputmethod.accessibility.AccessibilityUtils; 52c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.CompatUtils; 53c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.EditorInfoCompatUtils; 54c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputConnectionCompatUtils; 55c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputMethodManagerCompatWrapper; 56c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputMethodServiceCompatWrapper; 57c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputTypeCompatUtils; 581fef530ec7626fa16777f52b48191e61db8f46d4satokimport com.android.inputmethod.compat.SuggestionSpanUtils; 5928f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasaimport com.android.inputmethod.compat.VibratorCompatWrapper; 60c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.deprecated.LanguageSwitcherProxy; 61c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.deprecated.VoiceProxy; 6283ffff2a49beeb41874b7cb40819a75001f708e2Ken Wakasaimport com.android.inputmethod.keyboard.Key; 63c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.Keyboard; 64c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardActionListener; 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 1071ef6fc7e1519cedec9e84a64968bfba4212d0436Tadashi G. Takaoka // TODO: Remove this private option. 108af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka /** 109af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka * The private IME option used to indicate that the given text field needs 110af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka * ASCII code points input. 1111ef6fc7e1519cedec9e84a64968bfba4212d0436Tadashi G. Takaoka * 1121ef6fc7e1519cedec9e84a64968bfba4212d0436Tadashi G. Takaoka * @deprecated Use {@link EditorInfo#IME_FLAG_FORCE_ASCII}. 113af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka */ 1141ef6fc7e1519cedec9e84a64968bfba4212d0436Tadashi G. Takaoka @SuppressWarnings("dep-ann") 115af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka public static final String IME_OPTION_FORCE_ASCII = "forceAscii"; 116af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka 117af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka /** 118af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka * The subtype extra value used to indicate that the subtype keyboard layout is capable for 119af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka * typing ASCII characters. 120af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka */ 121af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka public static final String SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable"; 122af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka 123d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka /** 124294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima * The subtype extra value used to indicate that the subtype keyboard layout supports touch 125294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima * position correction. 126294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima */ 127294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima public static final String SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION = 128294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima "SupportTouchPositionCorrection"; 129294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima /** 130d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka * The subtype extra value used to indicate that the subtype keyboard layout should be loaded 131d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka * from the specified locale. 132d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka */ 133d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka public static final String SUBTYPE_EXTRA_VALUE_KEYBOARD_LOCALE = "KeyboardLocale"; 134d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka 1359e347d3d448e48229c46aad394ec9bd60cd5807bsatok private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100; 136fd0bd57deb53c4cce32810a61133fa44b45dbb7bKen Wakasa 137923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // How many continuous deletes at which to start deleting at a higher speed. 138923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int DELETE_ACCELERATE_AT = 20; 139923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Key events coming any faster than this are long-presses. 140d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani private static final int QUICK_PRESS = 200; 141a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 14259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private static final int PENDING_IMS_CALLBACK_DURATION = 800; 143055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 144cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard /** 145cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard * The name of the scheme used by the Package Manager to warn of a new package installation, 146cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard * replacement or removal. 147cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard */ 148cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard private static final String SCHEME_PACKAGE = "package"; 149cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 1500fe3611bee5095e7bd0fff2d0fdf8d5a13379132Jean Chalard // TODO: migrate this to SettingsValues 1517599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private int mSuggestionVisibility; 1527599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_VALUE 1537599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_value; 1547599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 1557599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_only_portrait_value; 1567599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_HIDE_VALUE 1577599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_hide_value; 1587599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 1597599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int[] SUGGESTION_VISIBILITY_VALUE_ARRAY = new int[] { 1607599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_VALUE, 1617599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE, 1627599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_HIDE_VALUE 1637599cfea4a2d56f4779452ec8e8742f7b9629cc0satok }; 1647599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 165120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Magic space: a space that should disappear on space/apostrophe insertion, move after the 166120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // punctuation on punctuation insertion, and become a real space on alpha char insertion. 167ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa // Weak space: a space that should be swapped only by suggestion strip punctuation. 168120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Double space: the state where the user pressed space twice quickly, which LatinIME 169120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // resolved as period-space. Undoing this converts the period to a space. 170120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Swap punctuation: the state where a (weak or magic) space and a punctuation from the 171120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // suggestion strip have just been swapped. Undoing this swaps them back. 172120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private static final int SPACE_STATE_NONE = 0; 173120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private static final int SPACE_STATE_DOUBLE = 1; 174120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private static final int SPACE_STATE_SWAP_PUNCTUATION = 2; 175120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private static final int SPACE_STATE_MAGIC = 3; 176120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private static final int SPACE_STATE_WEAK = 4; 177120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 178120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Current space state of the input method. This can be any of the above constants. 179120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private int mSpaceState; 180126698fdd256a2e3734634d3b923cabd800064baJean Chalard 1817a16a061e622539e54d7d649dcb8d4965aea575aJean Chalard private SettingsValues mSettingsValues; 18280b66bb166f7f45adfcadcb84788477df9930828Jean Chalard private InputAttributes mInputAttributes; 18317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 184d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka private View mExtractArea; 185abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka private View mKeyPreviewBackingView; 186913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka private View mSuggestionsContainer; 187913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka private SuggestionsView mSuggestionsView; 188923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private Suggest mSuggest; 1891b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka private CompletionInfo[] mApplicationSpecifiedCompletions; 190a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 191610f1dc8553cf2ed97e763a06a19380c4a6cd636satok private InputMethodManagerCompatWrapper mImm; 1922fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private Resources mResources; 1932fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private SharedPreferences mPrefs; 19471c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka private KeyboardSwitcher mKeyboardSwitcher; 1950ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private SubtypeSwitcher mSubtypeSwitcher; 196b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok private VoiceProxy mVoiceProxy; 197a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 198923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private UserDictionary mUserDictionary; 199979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private UserBigramDictionary mUserBigramDictionary; 200f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard private UserUnigramDictionary mUserUnigramDictionary; 20188562bec54658840dcce352127bdc15705c20a89Jean Chalard private boolean mIsUserDictionaryAvailable; 20236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 2039318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa private WordComposer mWordComposer = new WordComposer(); 204409220583333bdf06290dd9fd42f91b5c0d1b11asatok 20579efbed76f638be298493107fa2d0cd1b5eb529esatok private int mCorrectionMode; 20677da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard 207979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Keep track of the last selection range to decide if we need to show word alternatives 20877da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard private static final int NOT_A_CURSOR_POSITION = -1; 20977da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard private int mLastSelectionStart = NOT_A_CURSOR_POSITION; 21077da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard private int mLastSelectionEnd = NOT_A_CURSOR_POSITION; 211979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2124733609947c0ec74e460bd714fffca0518ade93aJean Chalard // Whether we are expecting an onUpdateSelection event to fire. If it does when we don't 2134733609947c0ec74e460bd714fffca0518ade93aJean Chalard // "expect" it, it means the user actually moved the cursor. 2144733609947c0ec74e460bd714fffca0518ade93aJean Chalard private boolean mExpectingUpdateSelection; 215923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mDeleteCount; 216923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastKeyTime; 217a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 218923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private AudioManager mAudioManager; 21917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard private boolean mSilentModeOn; // System-wide current configuration 220923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 22128f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa private VibratorCompatWrapper mVibrator; 22228f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa 223b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok // TODO: Move this flag to VoiceProxy 22481c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani private boolean mConfigurationChanging; 225466741d8a78965b8509bf527344f289e50873092Mike LeBeau 22638f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka // Member variables for remembering the current device orientation. 22738f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka private int mDisplayOrientation; 22838f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 229cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Object for reacting to adding/removing a dictionary pack. 230cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard private BroadcastReceiver mDictionaryPackInstallReceiver = 231cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard new DictionaryPackInstallBroadcastReceiver(this); 232cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 233dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Keeps track of most recently inserted text (multi-character key) for reverting 234dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani private CharSequence mEnteredText; 235dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 236604d80c67185954d4691ac775be59c499eee3b1csatok private final ComposingStateManager mComposingStateManager = 237fe2d90798ea409ee39d6f63942eb01bb7eed98e3satok ComposingStateManager.getInstance(); 238604d80c67185954d4691ac775be59c499eee3b1csatok 2394f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public final UIHandler mHandler = new UIHandler(this); 240d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 2414f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public static class UIHandler extends StaticInnerHandlerWrapper<LatinIME> { 242d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_SUGGESTIONS = 0; 24345f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_UPDATE_SHIFT_STATE = 1; 24445f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_VOICE_RESULTS = 2; 24545f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 3; 24645f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 4; 24745f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_SPACE_TYPED = 5; 24893246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka private static final int MSG_SET_BIGRAM_PREDICTIONS = 6; 24993246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka private static final int MSG_PENDING_IMS_CALLBACK = 7; 250175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka 25110dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private int mDelayBeforeFadeoutLanguageOnSpacebar; 25210dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private int mDelayUpdateSuggestions; 25310dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private int mDelayUpdateShiftState; 25410dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private int mDurationOfFadeoutLanguageOnSpacebar; 25510dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private float mFinalFadeoutFactorOfLanguageOnSpacebar; 25610dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private long mDoubleSpacesTurnIntoPeriodTimeout; 25738f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 2584f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public UIHandler(LatinIME outerInstance) { 2594f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa super(outerInstance); 26010dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka } 261175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka 26210dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka public void onCreate() { 26310dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka final Resources res = getOuterInstance().getResources(); 264175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDelayBeforeFadeoutLanguageOnSpacebar = res.getInteger( 265175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka R.integer.config_delay_before_fadeout_language_on_spacebar); 266175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDelayUpdateSuggestions = 267175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka res.getInteger(R.integer.config_delay_update_suggestions); 268175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDelayUpdateShiftState = 269175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka res.getInteger(R.integer.config_delay_update_shift_state); 270175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDurationOfFadeoutLanguageOnSpacebar = res.getInteger( 271175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka R.integer.config_duration_of_fadeout_language_on_spacebar); 272175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mFinalFadeoutFactorOfLanguageOnSpacebar = res.getInteger( 273175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka R.integer.config_final_fadeout_percentage_of_language_on_spacebar) / 100.0f; 274175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDoubleSpacesTurnIntoPeriodTimeout = res.getInteger( 275175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka R.integer.config_double_spaces_turn_into_period_timeout); 2764f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa } 2774f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa 278923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 279923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void handleMessage(Message msg) { 2804f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final LatinIME latinIme = getOuterInstance(); 2814f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final KeyboardSwitcher switcher = latinIme.mKeyboardSwitcher; 282c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka final LatinKeyboardView inputView = switcher.getKeyboardView(); 283923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (msg.what) { 284d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SUGGESTIONS: 2854f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.updateSuggestions(); 286d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 287d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SHIFT_STATE: 288de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka switcher.updateShiftState(); 289d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 290cb3320179d39a7983874697a0aa428b127675c9dJean Chalard case MSG_SET_BIGRAM_PREDICTIONS: 2914f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.updateBigramPredictions(); 29289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard break; 293d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_VOICE_RESULTS: 2944f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mVoiceProxy.handleVoiceResults(latinIme.preferCapitalization() 295de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked())); 296de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka break; 297de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka case MSG_FADEOUT_LANGUAGE_ON_SPACEBAR: 29823d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka setSpacebarTextFadeFactor(inputView, 29923d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka (1.0f + mFinalFadeoutFactorOfLanguageOnSpacebar) / 2, 3003708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka (Keyboard)msg.obj); 301de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_DISMISS_LANGUAGE_ON_SPACEBAR, msg.obj), 302175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDurationOfFadeoutLanguageOnSpacebar); 303de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka break; 304de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka case MSG_DISMISS_LANGUAGE_ON_SPACEBAR: 30523d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka setSpacebarTextFadeFactor(inputView, mFinalFadeoutFactorOfLanguageOnSpacebar, 3063708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka (Keyboard)msg.obj); 307d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 308923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 309923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 310d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 311d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateSuggestions() { 312d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 313175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS), mDelayUpdateSuggestions); 314d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 315d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 316d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateSuggestions() { 317d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 318d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 319d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 320d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public boolean hasPendingUpdateSuggestions() { 321d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka return hasMessages(MSG_UPDATE_SUGGESTIONS); 322d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 323d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 324d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateShiftKeyState() { 325d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 326175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE), mDelayUpdateShiftState); 327d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 328d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 329d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateShiftState() { 330d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 331d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 332d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 333cb3320179d39a7983874697a0aa428b127675c9dJean Chalard public void postUpdateBigramPredictions() { 334cb3320179d39a7983874697a0aa428b127675c9dJean Chalard removeMessages(MSG_SET_BIGRAM_PREDICTIONS); 335175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS), mDelayUpdateSuggestions); 33689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 33789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 338cb3320179d39a7983874697a0aa428b127675c9dJean Chalard public void cancelUpdateBigramPredictions() { 339cb3320179d39a7983874697a0aa428b127675c9dJean Chalard removeMessages(MSG_SET_BIGRAM_PREDICTIONS); 34089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 34189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 342d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void updateVoiceResults() { 343d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessage(obtainMessage(MSG_VOICE_RESULTS)); 344d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 345de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka 34623d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka private static void setSpacebarTextFadeFactor(LatinKeyboardView inputView, 3473708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka float fadeFactor, Keyboard oldKeyboard) { 34823d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka if (inputView == null) return; 34923d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka final Keyboard keyboard = inputView.getKeyboard(); 3503708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka if (keyboard == oldKeyboard) { 3514112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka inputView.updateSpacebar(fadeFactor, 3524112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka SubtypeSwitcher.getInstance().needsToDisplayLanguage( 3534112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka keyboard.mId.mLocale)); 35423d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka } 35523d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka } 35623d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka 357d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka public void startDisplayLanguageOnSpacebar(boolean localeChanged) { 3584f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final LatinIME latinIme = getOuterInstance(); 359de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka removeMessages(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR); 360de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka removeMessages(MSG_DISMISS_LANGUAGE_ON_SPACEBAR); 361c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka final LatinKeyboardView inputView = latinIme.mKeyboardSwitcher.getKeyboardView(); 362de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka if (inputView != null) { 3633708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka final Keyboard keyboard = latinIme.mKeyboardSwitcher.getKeyboard(); 364c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka // The language is always displayed when the delay is negative. 365c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka final boolean needsToDisplayLanguage = localeChanged 366175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka || mDelayBeforeFadeoutLanguageOnSpacebar < 0; 367de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka // The language is never displayed when the delay is zero. 368175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka if (mDelayBeforeFadeoutLanguageOnSpacebar != 0) { 36923d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka setSpacebarTextFadeFactor(inputView, 37023d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka needsToDisplayLanguage ? 1.0f : mFinalFadeoutFactorOfLanguageOnSpacebar, 37123d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka keyboard); 37217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 373c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka // The fadeout animation will start when the delay is positive. 374175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka if (localeChanged && mDelayBeforeFadeoutLanguageOnSpacebar > 0) { 375de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR, keyboard), 376175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDelayBeforeFadeoutLanguageOnSpacebar); 377de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 378de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 379de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 380fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 381fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public void startDoubleSpacesTimer() { 382fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka removeMessages(MSG_SPACE_TYPED); 383175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED), mDoubleSpacesTurnIntoPeriodTimeout); 384fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 385fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 386fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public void cancelDoubleSpacesTimer() { 387fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka removeMessages(MSG_SPACE_TYPED); 388fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 389fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 390fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public boolean isAcceptingDoubleSpaces() { 391fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka return hasMessages(MSG_SPACE_TYPED); 392fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 39338f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 39459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Working variables for the following methods. 39559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mIsOrientationChanging; 3965fd11a7f3367d51cea8dc83fb9675c93d82a2e4eJean Chalard private boolean mPendingSuccessiveImsCallback; 39759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mHasPendingStartInput; 39859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mHasPendingFinishInputView; 39959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mHasPendingFinishInput; 400e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka private EditorInfo mAppliedEditorInfo; 40159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 40259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void startOrientationChanging() { 403dd25e4fa2c7dd1e32a9e6f5fd21f54214919ef20Tadashi G. Takaoka removeMessages(MSG_PENDING_IMS_CALLBACK); 404dd25e4fa2c7dd1e32a9e6f5fd21f54214919ef20Tadashi G. Takaoka resetPendingImsCallback(); 40559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mIsOrientationChanging = true; 406055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 407f2c9a88887a303f3df8bee60788870946dfa55f7Tadashi G. Takaoka if (latinIme.isInputViewShown()) { 408f2c9a88887a303f3df8bee60788870946dfa55f7Tadashi G. Takaoka latinIme.mKeyboardSwitcher.saveKeyboardState(); 409f2c9a88887a303f3df8bee60788870946dfa55f7Tadashi G. Takaoka } 41059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 41159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 41259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void resetPendingImsCallback() { 41359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInputView = false; 41459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInput = false; 41559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingStartInput = false; 41659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 41759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 418e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka private void executePendingImsCallback(LatinIME latinIme, EditorInfo editorInfo, 41959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka boolean restarting) { 42059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mHasPendingFinishInputView) 42159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputViewInternal(mHasPendingFinishInput); 42259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mHasPendingFinishInput) 42359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputInternal(); 42459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mHasPendingStartInput) 425e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka latinIme.onStartInputInternal(editorInfo, restarting); 42659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka resetPendingImsCallback(); 42759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 42859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 429e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka public void onStartInput(EditorInfo editorInfo, boolean restarting) { 43059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { 43159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Typically this is the second onStartInput after orientation changed. 43259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingStartInput = true; 43359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } else { 43459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mIsOrientationChanging && restarting) { 43559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // This is the first onStartInput after orientation changed. 43659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mIsOrientationChanging = false; 4375fd11a7f3367d51cea8dc83fb9675c93d82a2e4eJean Chalard mPendingSuccessiveImsCallback = true; 43859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 43959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 440e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka executePendingImsCallback(latinIme, editorInfo, restarting); 441e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka latinIme.onStartInputInternal(editorInfo, restarting); 442055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 443055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 444055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 445e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka public void onStartInputView(EditorInfo editorInfo, boolean restarting) { 4466b7100fecaaaf0e8e42c4d2ccebac165e89e79bfTadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK) 4476b7100fecaaaf0e8e42c4d2ccebac165e89e79bfTadashi G. Takaoka && KeyboardId.equivalentEditorInfoForKeyboard(editorInfo, mAppliedEditorInfo)) { 448e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka // Typically this is the second onStartInputView after orientation changed. 449e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka resetPendingImsCallback(); 450e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka } else { 4515fd11a7f3367d51cea8dc83fb9675c93d82a2e4eJean Chalard if (mPendingSuccessiveImsCallback) { 452e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka // This is the first onStartInputView after orientation changed. 4535fd11a7f3367d51cea8dc83fb9675c93d82a2e4eJean Chalard mPendingSuccessiveImsCallback = false; 454e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka resetPendingImsCallback(); 455e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_PENDING_IMS_CALLBACK), 456e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka PENDING_IMS_CALLBACK_DURATION); 457e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka } 458e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 459e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka executePendingImsCallback(latinIme, editorInfo, restarting); 460e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka latinIme.onStartInputViewInternal(editorInfo, restarting); 461e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mAppliedEditorInfo = editorInfo; 462e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka } 46359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 46459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 46559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInputView(boolean finishingInput) { 46659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { 46759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Typically this is the first onFinishInputView after orientation changed. 46859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInputView = true; 46959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } else { 47059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 47159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputViewInternal(finishingInput); 472e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mAppliedEditorInfo = null; 47338f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 47438f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 475ffd156c77e93a54b704780b46886ba597d1c77cbTadashi G. Takaoka 47659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInput() { 47759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { 47859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Typically this is the first onFinishInput after orientation changed. 47959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInput = true; 48059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } else { 48159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 48259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka executePendingImsCallback(latinIme, null, false); 48359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputInternal(); 484ffd156c77e93a54b704780b46886ba597d1c77cbTadashi G. Takaoka } 485ffd156c77e93a54b704780b46886ba597d1c77cbTadashi G. Takaoka } 48638f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 48738f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 4887e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 4897e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka public void onCreate() { 49027d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 49127d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mPrefs = prefs; 49227d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa LatinImeLogger.init(this, prefs); 4936d9021527a38ba1e94225020389621a0d7227aa1satok LanguageSwitcherProxy.init(this, prefs); 494bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka InputMethodManagerCompatWrapper.init(this); 495ef5dfc480c7a3e3e34a20b7aacc731942e7a0578Tadashi G. Takaoka SubtypeSwitcher.init(this); 49627d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa KeyboardSwitcher.init(this, prefs); 4972ac5988f84b5c38d313951a3d7faddebf5f25e04Tadashi G. Takaoka AccessibilityUtils.init(this); 498363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 499923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onCreate(); 500363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 501bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka mImm = InputMethodManagerCompatWrapper.getInstance(); 5020ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 5030ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mKeyboardSwitcher = KeyboardSwitcher.getInstance(); 50428f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa mVibrator = VibratorCompatWrapper.getInstance(this); 50510dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka mHandler.onCreate(); 5069e2d810dc524380ca1db6b384cfb00b4401585e5Tadashi G. Takaoka DEBUG = LatinImeLogger.sDBG; 507363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 508363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka final Resources res = getResources(); 509363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka mResources = res; 510fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard 51128f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa loadSettings(); 51228f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa 513dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard // TODO: remove the following when it's not needed by updateCorrectionMode() any more 514644c8b7c96627199c13297082e4566adae159bf3Jean Chalard mInputAttributes = new InputAttributes(null, false /* isFullscreenMode */); 5159502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Utils.GCUtils.getInstance().reset(); 516979f8690967ff5409fe18f5085858ccdb8e0ccf1satok boolean tryGC = true; 5179502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { 518979f8690967ff5409fe18f5085858ccdb8e0ccf1satok try { 5190ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 520979f8690967ff5409fe18f5085858ccdb8e0ccf1satok tryGC = false; 521979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } catch (OutOfMemoryError e) { 5229502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka tryGC = Utils.GCUtils.getInstance().tryGCOrWait("InitSuggest", e); 523979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 524979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 525979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 526f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka mDisplayOrientation = res.getConfiguration().orientation; 527b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 528cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Register to receive ringer mode change and network state change. 529cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Also receive installation and removal of a dictionary pack. 530123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final IntentFilter filter = new IntentFilter(); 531123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); 532123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 533923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project registerReceiver(mReceiver, filter); 534b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy = VoiceProxy.init(this, prefs, mHandler); 535cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 536cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final IntentFilter packageFilter = new IntentFilter(); 537cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 538cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 539cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addDataScheme(SCHEME_PACKAGE); 540cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard registerReceiver(mDictionaryPackInstallReceiver, packageFilter); 541646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard 542646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard final IntentFilter newDictFilter = new IntentFilter(); 543646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard newDictFilter.addAction( 544646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard DictionaryPackInstallBroadcastReceiver.NEW_DICTIONARY_INTENT_ACTION); 545646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard registerReceiver(mDictionaryPackInstallReceiver, newDictFilter); 546923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 54736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 54817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // Has to be package-visible for unit tests 54917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard /* package */ void loadSettings() { 55017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this); 55117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (null == mSubtypeSwitcher) mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 5527a16a061e622539e54d7d649dcb8d4965aea575aJean Chalard mSettingsValues = new SettingsValues(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr()); 55314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary()); 55417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 55517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 5560ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private void initSuggest() { 557cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); 558ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr); 55936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 560309bff562fbaf47488e6bf6636840f00574187d8Jean Chalard final Resources res = mResources; 561ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard final Locale savedLocale = LocaleUtils.setSystemLocale(res, keyboardLocale); 56214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard final ContactsDictionary oldContactsDictionary; 56336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani if (mSuggest != null) { 56414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard oldContactsDictionary = mSuggest.getContactsDictionary(); 56536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mSuggest.close(); 56614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } else { 56714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard oldContactsDictionary = null; 56836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 569979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 5708efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka int mainDicResId = Utils.getMainDictionaryResourceId(res); 571cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mSuggest = new Suggest(this, mainDicResId, keyboardLocale); 57217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.mAutoCorrectEnabled) { 57317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); 57417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 575e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 576cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mUserDictionary = new UserDictionary(this, localeStr); 577923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mSuggest.setUserDictionary(mUserDictionary); 57888562bec54658840dcce352127bdc15705c20a89Jean Chalard mIsUserDictionaryAvailable = mUserDictionary.isEnabled(); 579e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 58014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard resetContactsDictionary(oldContactsDictionary); 581e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 582f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard mUserUnigramDictionary 583f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard = new UserUnigramDictionary(this, this, localeStr, Suggest.DIC_USER_UNIGRAM); 584f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard mSuggest.setUserUnigramDictionary(mUserUnigramDictionary); 585e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 586f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard mUserBigramDictionary 587f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard = new UserBigramDictionary(this, this, localeStr, Suggest.DIC_USER_BIGRAM); 588e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.setUserBigramDictionary(mUserBigramDictionary); 589e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 590e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani updateCorrectionMode(); 59136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 592ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard LocaleUtils.setSystemLocale(res, savedLocale); 593923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 59436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 59514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard /** 59614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * Resets the contacts dictionary in mSuggest according to the user settings. 59714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * 59814051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * This method takes an optional contacts dictionary to use. Since the contacts dictionary 59914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * does not depend on the locale, it can be reused across different instances of Suggest. 60014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * The dictionary will also be opened or closed as necessary depending on the settings. 60114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * 60214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * @param oldContactsDictionary an optional dictionary to use, or null 60314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard */ 60414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard private void resetContactsDictionary(final ContactsDictionary oldContactsDictionary) { 60514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard final boolean shouldSetDictionary = (null != mSuggest && mSettingsValues.mUseContactsDict); 60614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard 60714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard final ContactsDictionary dictionaryToUse; 60814051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (!shouldSetDictionary) { 60914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // Make sure the dictionary is closed. If it is already closed, this is a no-op, 61014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // so it's safe to call it anyways. 61114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (null != oldContactsDictionary) oldContactsDictionary.close(); 61214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard dictionaryToUse = null; 61314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } else if (null != oldContactsDictionary) { 61414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // Make sure the old contacts dictionary is opened. If it is already open, this is a 61514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // no-op, so it's safe to call it anyways. 61614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard oldContactsDictionary.reopen(this); 61714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard dictionaryToUse = oldContactsDictionary; 61814051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } else { 61914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard dictionaryToUse = new ContactsDictionary(this, Suggest.DIC_CONTACTS); 62014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } 62114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard 62214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (null != mSuggest) { 62314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard mSuggest.setContactsDictionary(dictionaryToUse); 62414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } 625699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard } 626699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard 627cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard /* package private */ void resetSuggestMainDict() { 628cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); 629ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr); 630cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard int mainDicResId = Utils.getMainDictionaryResourceId(mResources); 631cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mSuggest.resetMainDict(this, mainDicResId, keyboardLocale); 632cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard } 633cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 634466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 635466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onDestroy() { 636e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa if (mSuggest != null) { 637e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.close(); 638e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest = null; 639979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 640923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project unregisterReceiver(mReceiver); 641cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard unregisterReceiver(mDictionaryPackInstallReceiver); 642b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.destroy(); 643979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 644979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.onDestroy(); 645923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onDestroy(); 646923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 647923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 648923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 649923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onConfigurationChanged(Configuration conf) { 650dc64b138b5e3fb3706c0818d0a308fe6e36985b0Tadashi G. Takaoka mSubtypeSwitcher.onConfigurationChanged(conf); 651604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.onFinishComposingText(); 652b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani // If orientation changed while predicting, commit the change 653f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka if (mDisplayOrientation != conf.orientation) { 654f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka mDisplayOrientation = conf.orientation; 655f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka mHandler.startOrientationChanging(); 6569351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 657466741d8a78965b8509bf527344f289e50873092Mike LeBeau commitTyped(ic); 658466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (ic != null) ic.finishComposingText(); // For voice input 6592fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka if (isShowingOptionDialog()) 6602fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka mOptionsDialog.dismiss(); 661b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 6628b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 66381c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani mConfigurationChanging = true; 664923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onConfigurationChanged(conf); 665b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.onConfigurationChanged(conf); 66681c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani mConfigurationChanging = false; 66788fc9d44186120f9edc5cf7ec0e2af85260fed04satok 66888fc9d44186120f9edc5cf7ec0e2af85260fed04satok // This will work only when the subtype is not supported. 66988fc9d44186120f9edc5cf7ec0e2af85260fed04satok LanguageSwitcherProxy.onConfigurationChanged(conf); 670923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 671b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 672923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 673923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public View onCreateInputView() { 6746c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka return mKeyboardSwitcher.onCreateInputView(); 6756c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka } 6766c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka 6776c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka @Override 6786c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka public void setInputView(View view) { 6796c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka super.setInputView(view); 680d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka mExtractArea = getWindow().getWindow().getDecorView() 681d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka .findViewById(android.R.id.extractArea); 682abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka mKeyPreviewBackingView = view.findViewById(R.id.key_preview_backing); 683913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsContainer = view.findViewById(R.id.suggestions_container); 684913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView = (SuggestionsView) view.findViewById(R.id.suggestions_view); 685913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) 686913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.setListener(this, view); 687f5fe245df0548ea0a8ec607f2392de0fe02c141dTadashi G. Takaoka if (LatinImeLogger.sVISUALDEBUG) { 688f5fe245df0548ea0a8ec607f2392de0fe02c141dTadashi G. Takaoka mKeyPreviewBackingView.setBackgroundColor(0x10FF0000); 689f5fe245df0548ea0a8ec607f2392de0fe02c141dTadashi G. Takaoka } 690923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 691923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 692923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 693c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka public void setCandidatesView(View view) { 694c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka // To ensure that CandidatesView will never be set. 695c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return; 696923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 697923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 698a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker @Override 699e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka public void onStartInput(EditorInfo editorInfo, boolean restarting) { 700e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mHandler.onStartInput(editorInfo, restarting); 70159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 70259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 70359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka @Override 704e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka public void onStartInputView(EditorInfo editorInfo, boolean restarting) { 705e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mHandler.onStartInputView(editorInfo, restarting); 70659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 70759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 70859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka @Override 70959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInputView(boolean finishingInput) { 71059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHandler.onFinishInputView(finishingInput); 71159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 71238f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 71359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka @Override 71459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInput() { 71559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHandler.onFinishInput(); 71659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 71759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 718e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka private void onStartInputInternal(EditorInfo editorInfo, boolean restarting) { 719e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka super.onStartInput(editorInfo, restarting); 72059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 72159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 722e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka private void onStartInputViewInternal(EditorInfo editorInfo, boolean restarting) { 723e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka super.onStartInputView(editorInfo, restarting); 72445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 725c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka LatinKeyboardView inputView = switcher.getKeyboardView(); 7268e09172df1bb176cc899940862c56bed9b9aec4esatok 72789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (DEBUG) { 728e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka Log.d(TAG, "onStartInputView: editorInfo:" + ((editorInfo == null) ? "none" 729f0f726464dcb5b3cef4f8e703659b35ca62430b5Tadashi G. Takaoka : String.format("inputType=0x%08x imeOptions=0x%08x", 730e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka editorInfo.inputType, editorInfo.imeOptions))); 731910b73127fa207dd26ec8124000262523b0aac0csatok } 7327ef235f53f2291f22ddf8c56be9860a218b25bbbTadashi G. Takaoka LatinImeLogger.onStartInputView(editorInfo); 733923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In landscape mode, this method gets called without the input view being created. 734979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (inputView == null) { 735923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 736923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 737923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 738b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette // Forward this event to the accessibility utilities, if enabled. 739b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette final AccessibilityUtils accessUtils = AccessibilityUtils.getInstance(); 740b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette if (accessUtils.isTouchExplorationEnabled()) { 741e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka accessUtils.onStartInputViewInternal(editorInfo, restarting); 742b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette } 743b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette 7448d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka mSubtypeSwitcher.updateParametersOnStartInputView(); 7454ab730dbd34fad323063f2ffd31ce33de746668dsatok 746055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka // Most such things we decide below in initializeInputAttributesAndGetMode, but we need to 747055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka // know now whether this is a password text field, because we need to know now whether we 748055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka // want to enable the voice button. 749055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka final VoiceProxy voiceIme = mVoiceProxy; 750e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka final int inputType = (editorInfo != null) ? editorInfo.inputType : 0; 7513be0039164f5e2060b83d0699e293ffc76384732Tadashi G. Takaoka voiceIme.resetVoiceStates(InputTypeCompatUtils.isPasswordInputType(inputType) 7523be0039164f5e2060b83d0699e293ffc76384732Tadashi G. Takaoka || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)); 753c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 754b2b1eb5ca5a52648eea70920b9bd745b07d3ddfaTadashi G. Takaoka // The EditorInfo might have a flag that affects fullscreen mode. 755b2b1eb5ca5a52648eea70920b9bd745b07d3ddfaTadashi G. Takaoka // Note: This call should be done by InputMethodService? 756b2b1eb5ca5a52648eea70920b9bd745b07d3ddfaTadashi G. Takaoka updateFullscreenMode(); 75780b66bb166f7f45adfcadcb84788477df9930828Jean Chalard mInputAttributes = new InputAttributes(editorInfo, isFullscreenMode()); 758ccc35f7fa74860a8d737a4e9ff01fc0168dd329dJean Chalard mApplicationSpecifiedCompletions = null; 759c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 760c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.closing(); 761c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mEnteredText = null; 7623651220327c051d8017045aa5e8919461507b3f8Jean Chalard mWordComposer.reset(); 763c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mDeleteCount = 0; 764120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 765c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 76617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 76717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard updateCorrectionMode(); 7682ac5988f84b5c38d313951a3d7faddebf5f25e04Tadashi G. Takaoka updateSuggestionVisibility(mResources); 76917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 77017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSuggest != null && mSettingsValues.mAutoCorrectEnabled) { 77117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); 772549e295dc113bff50077c3c355dcd94af09a1b2fTadashi G. Takaoka } 773e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mVoiceProxy.loadSettings(editorInfo, mPrefs); 77417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // This will work only when the subtype is not supported. 77517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard LanguageSwitcherProxy.loadSettings(); 77617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 777c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (mSubtypeSwitcher.isKeyboardMode()) { 778e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka switcher.loadKeyboard(editorInfo, mSettingsValues); 779c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 780c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 781913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) 782913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.clear(); 783913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShownInternal( 784913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka isSuggestionsStripVisible(), /* needsInputViewShown */ false); 785c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // Delay updating suggestions because keyboard input view may not be shown at this point. 786c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mHandler.postUpdateSuggestions(); 787ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa mHandler.cancelDoubleSpacesTimer(); 788c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 789240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard inputView.setKeyPreviewPopupEnabled(mSettingsValues.mKeyPreviewPopupOn, 790240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard mSettingsValues.mKeyPreviewPopupDismissDelay); 791c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.setProximityCorrectionEnabled(true); 792c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 793055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka voiceIme.onStartInputView(inputView.getWindowToken()); 794c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 795c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); 796c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 797c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 798923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 799e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka public void onWindowHidden() { 800e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka super.onWindowHidden(); 801f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 802e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka if (inputView != null) inputView.closing(); 803e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka } 804e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka 80559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void onFinishInputInternal() { 806923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onFinishInput(); 807a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 808979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 809979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 810b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.flushVoiceInputLogs(mConfigurationChanging); 811409220583333bdf06290dd9fd42f91b5c0d1b11asatok 812f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 813d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa if (inputView != null) inputView.closing(); 814f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard if (mUserUnigramDictionary != null) mUserUnigramDictionary.flushPendingWrites(); 815979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mUserBigramDictionary != null) mUserBigramDictionary.flushPendingWrites(); 816466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 817466741d8a78965b8509bf527344f289e50873092Mike LeBeau 81859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void onFinishInputViewInternal(boolean finishingInput) { 8196495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa super.onFinishInputView(finishingInput); 820055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka mKeyboardSwitcher.onFinishInputView(); 821f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 8225f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka if (inputView != null) inputView.cancelAllMessages(); 823d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka // Remove pending messages related to update suggestions 824d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 8256495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa } 8266495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa 8276495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa @Override 828466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onUpdateExtractedText(int token, ExtractedText text) { 829466741d8a78965b8509bf527344f289e50873092Mike LeBeau super.onUpdateExtractedText(token, text); 830b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.showPunctuationHintIfNecessary(); 831923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 832923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 833923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 834923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onUpdateSelection(int oldSelStart, int oldSelEnd, 835923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int newSelStart, int newSelEnd, 836923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int candidatesStart, int candidatesEnd) { 837923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, 838923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project candidatesStart, candidatesEnd); 839466741d8a78965b8509bf527344f289e50873092Mike LeBeau 840466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (DEBUG) { 841466741d8a78965b8509bf527344f289e50873092Mike LeBeau Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart 842466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ose=" + oldSelEnd 843025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lss=" + mLastSelectionStart 844025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lse=" + mLastSelectionEnd 845466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nss=" + newSelStart 846466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nse=" + newSelEnd 847466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", cs=" + candidatesStart 848466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ce=" + candidatesEnd); 849466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 850466741d8a78965b8509bf527344f289e50873092Mike LeBeau 851b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.setCursorAndSelection(newSelEnd, newSelStart); 8524f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 853923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // If the current selection in the text view changes, we should 854923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // clear whatever candidate text we have. 855025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa final boolean selectionChanged = (newSelStart != candidatesEnd 856025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa || newSelEnd != candidatesEnd) && mLastSelectionStart != newSelStart; 857025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa final boolean candidatesCleared = candidatesStart == -1 && candidatesEnd == -1; 8584733609947c0ec74e460bd714fffca0518ade93aJean Chalard if (!mExpectingUpdateSelection) { 859cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard // TAKE CARE: there is a race condition when we enter this test even when the user 860cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard // did not explicitly move the cursor. This happens when typing fast, where two keys 861cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard // turn this flag on in succession and both onUpdateSelection() calls arrive after 862cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard // the second one - the first call successfully avoids this test, but the second one 863cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard // enters. For the moment we rely on candidatesCleared to further reduce the impact. 864120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (SPACE_STATE_WEAK == mSpaceState) { 865120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Test for no WEAK_SPACE action because there is a race condition that may end up 866120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // in coming here on a normal key press. We set this to NONE because after 867120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // a cursor move, we don't want the suggestion strip to swap the space with the 868120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // newly inserted punctuation. 869120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 870126698fdd256a2e3734634d3b923cabd800064baJean Chalard } 871196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (((mWordComposer.isComposingWord()) 8724c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard || mVoiceProxy.isVoiceInputHighlighted()) 8734c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard && (selectionChanged || candidatesCleared)) { 8743651220327c051d8017045aa5e8919461507b3f8Jean Chalard mWordComposer.reset(); 875cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard updateSuggestions(); 8764c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard final InputConnection ic = getCurrentInputConnection(); 8774c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard if (ic != null) { 8784c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard ic.finishComposingText(); 8794c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard } 880604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.onFinishComposingText(); 8814c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard mVoiceProxy.setVoiceInputHighlighted(false); 882196d82cdd740580ed79d801483dbc282be85d076Jean Chalard } else if (!mWordComposer.isComposingWord()) { 883cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard mWordComposer.reset(); 884cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard updateSuggestions(); 8854c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard } 8864733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 8874733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = false; 888d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateShiftKeyState(); 8896b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // TODO: Decide to call restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() or not 8906b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // here. It would probably be too expensive to call directly here but we may want to post a 8916b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // message to delay it. The point would be to unify behavior between backspace to the 8926b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // end of a word and manually put the pointer at the end of the word. 893466741d8a78965b8509bf527344f289e50873092Mike LeBeau 894979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Make a note of the cursor position 895979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionStart = newSelStart; 896979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionEnd = newSelEnd; 8977a8dac55278cedd838be325f56b4c52d973c61f5satok } 8987a8dac55278cedd838be325f56b4c52d973c61f5satok 899c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 900c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has clicked on the extracted text view, 901c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * when running in fullscreen mode. The default implementation hides 902913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * the suggestions view when this happens, but only if the extracted text 903c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * editor has a vertical scroll bar because its text doesn't fit. 904c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 905913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * cause the suggestions strip to disappear and re-appear. 906c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 907c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 908c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedTextClicked() { 909fe5364c825058f6c34c0f42135a5520b77525a28Jean Chalard if (isSuggestionsRequested()) return; 910c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 911c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedTextClicked(); 912c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 913c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 914c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 915c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has performed a cursor movement in the 916c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * extracted text view, when it is running in fullscreen mode. The default 917913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * implementation hides the suggestions view when a vertical movement 918c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * happens, but only if the extracted text editor has a vertical scroll bar 919c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * 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 onExtractedCursorMovement(int dx, int dy) { 925fe5364c825058f6c34c0f42135a5520b77525a28Jean Chalard if (isSuggestionsRequested()) return; 926c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 927c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedCursorMovement(dx, dy); 928c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 929c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 930923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 931923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void hideWindow() { 932979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 933c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka mKeyboardSwitcher.onHideWindow(); 934979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 935923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (TRACE) Debug.stopMethodTracing(); 9366e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mOptionsDialog != null && mOptionsDialog.isShowing()) { 9376e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog.dismiss(); 9386e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog = null; 9396e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 940b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.hideVoiceWindow(mConfigurationChanging); 941923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.hideWindow(); 942923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 943923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 944923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 9451b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka public void onDisplayCompletions(CompletionInfo[] applicationSpecifiedCompletions) { 946979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (DEBUG) { 947a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa Log.i(TAG, "Received completions:"); 948bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok if (applicationSpecifiedCompletions != null) { 949bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok for (int i = 0; i < applicationSpecifiedCompletions.length; i++) { 950bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok Log.i(TAG, " #" + i + ": " + applicationSpecifiedCompletions[i]); 951bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok } 952923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 953923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 954dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard if (mInputAttributes.mApplicationSpecifiedCompletionOn) { 9551b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletions = applicationSpecifiedCompletions; 9561b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (applicationSpecifiedCompletions == null) { 957b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani clearSuggestions(); 958923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 959923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 960a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 9617e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords.Builder builder = new SuggestedWords.Builder() 9621b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka .setApplicationSpecifiedCompletions(applicationSpecifiedCompletions) 9635238df54ad3f648d09d5288f00b0a9d3c0593832Tadashi G. Takaoka .setTypedWordValid(false) 9645238df54ad3f648d09d5288f00b0a9d3c0593832Tadashi G. Takaoka .setHasMinimalSuggestion(false); 965979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // When in fullscreen mode, show completions generated by the application 9667e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(builder.build()); 967117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard mWordComposer.deleteAutoCorrection(); 968c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShown(true); 969923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 970923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 971923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 972c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka private void setSuggestionStripShownInternal(boolean shown, boolean needsInputViewShown) { 973913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka // TODO: Modify this if we support suggestions with hard keyboard 974913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (onEvaluateInputViewShown() && mSuggestionsContainer != null) { 975913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka final boolean shouldShowSuggestions = shown 9767a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka && (needsInputViewShown ? mKeyboardSwitcher.isInputViewShown() : true); 9774b1780fa9571409d65d9797d47949ffafaf0f083Tadashi G. Takaoka if (isFullscreenMode()) { 978913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsContainer.setVisibility( 979913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka shouldShowSuggestions ? View.VISIBLE : View.GONE); 9807a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka } else { 981913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsContainer.setVisibility( 982913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka shouldShowSuggestions ? View.VISIBLE : View.INVISIBLE); 9837a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka } 984923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 985923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 986a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 987c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka private void setSuggestionStripShown(boolean shown) { 988c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShownInternal(shown, /* needsInputViewShown */true); 989543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa } 990543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa 991543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa @Override 992923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onComputeInsets(InputMethodService.Insets outInsets) { 993923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onComputeInsets(outInsets); 994f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka final KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 995913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (inputView == null || mSuggestionsContainer == null) 99646ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka return; 997d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka // In fullscreen mode, the height of the extract area managed by InputMethodService should 998d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka // be considered. 999d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka // See {@link android.inputmethodservice.InputMethodService#onComputeInsets}. 1000d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka final int extractHeight = isFullscreenMode() ? mExtractArea.getHeight() : 0; 1001abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka final int backingHeight = (mKeyPreviewBackingView.getVisibility() == View.GONE) ? 0 1002abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka : mKeyPreviewBackingView.getHeight(); 100359010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka final int suggestionsHeight = (mSuggestionsContainer.getVisibility() == View.GONE) ? 0 100459010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka : mSuggestionsContainer.getHeight(); 1005d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka final int extraHeight = extractHeight + backingHeight + suggestionsHeight; 1006abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka int touchY = extraHeight; 10079e347d3d448e48229c46aad394ec9bd60cd5807bsatok // Need to set touchable region only if input view is being shown 100846ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka if (mKeyboardSwitcher.isInputViewShown()) { 1009913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsContainer.getVisibility() == View.VISIBLE) { 101059010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka touchY -= suggestionsHeight; 10119e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 10127a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka final int touchWidth = inputView.getWidth(); 1013abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka final int touchHeight = inputView.getHeight() + extraHeight 10147a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // Extend touchable region below the keyboard. 10157a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka + EXTENDED_TOUCHABLE_REGION_HEIGHT; 10169e347d3d448e48229c46aad394ec9bd60cd5807bsatok if (DEBUG) { 10177a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka Log.d(TAG, "Touchable region: y=" + touchY + " width=" + touchWidth 10187a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka + " height=" + touchHeight); 10199e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 10207a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka setTouchableRegionCompat(outInsets, 0, touchY, touchWidth, touchHeight); 10219e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 102246ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka outInsets.contentTopInsets = touchY; 102346ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka outInsets.visibleTopInsets = touchY; 1024923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1025a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1026923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 1027979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public boolean onEvaluateFullscreenMode() { 10289751a626ec9b2e771afa5b3757e8f8498a328683Tadashi G. Takaoka // Reread resource value here, because this method is called by framework anytime as needed. 10299751a626ec9b2e771afa5b3757e8f8498a328683Tadashi G. Takaoka final boolean isFullscreenModeAllowed = 10309751a626ec9b2e771afa5b3757e8f8498a328683Tadashi G. Takaoka mSettingsValues.isFullscreenModeAllowed(getResources()); 10319751a626ec9b2e771afa5b3757e8f8498a328683Tadashi G. Takaoka return super.onEvaluateFullscreenMode() && isFullscreenModeAllowed; 103259010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka } 103359010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka 103459010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka @Override 103559010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka public void updateFullscreenMode() { 103659010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka super.updateFullscreenMode(); 1037f80b6a06992ae08ca3601f4fbc6da550fd9ac730Tadashi G. Takaoka 103859010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka if (mKeyPreviewBackingView == null) return; 1039549e295dc113bff50077c3c355dcd94af09a1b2fTadashi G. Takaoka // In fullscreen mode, no need to have extra space to show the key preview. 104059010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka // If not, we should have extra space above the keyboard to show the key preview. 1041549e295dc113bff50077c3c355dcd94af09a1b2fTadashi G. Takaoka mKeyPreviewBackingView.setVisibility(isFullscreenMode() ? View.GONE : View.VISIBLE); 1042979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1043979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1044979f8690967ff5409fe18f5085858ccdb8e0ccf1satok @Override 1045923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 1046923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 1047e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_BACK: 10482cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka if (event.getRepeatCount() == 0) { 10492cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka if (mSuggestionsView != null && mSuggestionsView.handleBack()) { 10502cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka return true; 10512cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka } 10522cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka final LatinKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); 10532cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka if (keyboardView != null && keyboardView.handleBack()) { 10546e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani return true; 10556e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 1056e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 1057e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 1058923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1059923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyDown(keyCode, event); 1060923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1061923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1062923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 1063923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 1064923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 1065e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_DOWN: 1066e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_UP: 1067e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_LEFT: 1068e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_RIGHT: 1069e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka // Enable shift key and DPAD to do selections 1070e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mKeyboardSwitcher.isInputViewShown() 1071e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka && mKeyboardSwitcher.isShiftedOrShiftLocked()) { 1072e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent newEvent = new KeyEvent(event.getDownTime(), event.getEventTime(), 1073e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getAction(), event.getKeyCode(), event.getRepeatCount(), 1074e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getDeviceId(), event.getScanCode(), 1075e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON); 10769351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1077e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (ic != null) 1078e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka ic.sendKeyEvent(newEvent); 1079e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka return true; 1080e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 1081e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 1082923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1083923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyUp(keyCode, event); 1084923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1085923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 10869351550dc6af7859e5280e16144c9386a37b976dKen Wakasa public void commitTyped(final InputConnection ic) { 1087196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (!mWordComposer.isComposingWord()) return; 10883651220327c051d8017045aa5e8919461507b3f8Jean Chalard final CharSequence typedWord = mWordComposer.getTypedWord(); 10890fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard mWordComposer.onCommitWord(WordComposer.COMMIT_TYPE_USER_TYPED_WORD); 10903651220327c051d8017045aa5e8919461507b3f8Jean Chalard if (typedWord.length() > 0) { 10919351550dc6af7859e5280e16144c9386a37b976dKen Wakasa if (ic != null) { 10923651220327c051d8017045aa5e8919461507b3f8Jean Chalard ic.commitText(typedWord, 1); 1093923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 10943651220327c051d8017045aa5e8919461507b3f8Jean Chalard addToUserUnigramAndBigramDictionaries(typedWord, 1095f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard UserUnigramDictionary.FREQUENCY_FOR_TYPED); 1096923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 10978558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa updateSuggestions(); 1098923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1099923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1100b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public boolean getCurrentAutoCapsState() { 11019351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 11021c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani EditorInfo ei = getCurrentInputEditorInfo(); 110317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.mAutoCap && ic != null && ei != null 110417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && ei.inputType != InputType.TYPE_NULL) { 1105b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return ic.getCursorCapsMode(ei.inputType) != 0; 11061c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 1107b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 11081c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 11091c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 1110b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard // "ic" may be null 1111b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard private void swapSwapperAndSpaceWhileInBatchEdit(final InputConnection ic) { 1112b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard if (null == ic) return; 1113923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence lastTwo = ic.getTextBeforeCursor(2, 0); 1114863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called. 1115923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastTwo != null && lastTwo.length() == 2 1116863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard && lastTwo.charAt(0) == Keyboard.CODE_SPACE) { 1117923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 1118923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(lastTwo.charAt(1) + " ", 1); 1119b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 11204ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 11214ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 11224ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1123120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private boolean maybeDoubleSpaceWhileInBatchEdit(final InputConnection ic) { 1124120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (mCorrectionMode == Suggest.CORRECTION_NONE) return false; 1125120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (ic == null) return false; 11262b4eabed2bfe982b91a994c145401d98894e6ef5Jean Chalard final CharSequence lastThree = ic.getTextBeforeCursor(3, 0); 1127923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastThree != null && lastThree.length() == 3 11289351550dc6af7859e5280e16144c9386a37b976dKen Wakasa && Utils.canBeFollowedByPeriod(lastThree.charAt(0)) 1129571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(1) == Keyboard.CODE_SPACE 1130fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka && lastThree.charAt(2) == Keyboard.CODE_SPACE 1131fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka && mHandler.isAcceptingDoubleSpaces()) { 1132fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka mHandler.cancelDoubleSpacesTimer(); 1133923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 1134923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(". ", 1); 1135b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1136120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return true; 1137923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1138120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return false; 1139923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1140a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1141b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard // "ic" must not be null 11428fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka private static void maybeRemovePreviousPeriod(final InputConnection ic, CharSequence text) { 114341a519729505a877844f2c57a33509c302dddbceKen Wakasa // When the text's first character is '.', remove the previous period 114441a519729505a877844f2c57a33509c302dddbceKen Wakasa // if there is one. 1145b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard final CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 11464ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa if (lastOne != null && lastOne.length() == 1 1147571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastOne.charAt(0) == Keyboard.CODE_PERIOD 1148571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && text.charAt(0) == Keyboard.CODE_PERIOD) { 114941a519729505a877844f2c57a33509c302dddbceKen Wakasa ic.deleteSurroundingText(1, 0); 115041a519729505a877844f2c57a33509c302dddbceKen Wakasa } 115141a519729505a877844f2c57a33509c302dddbceKen Wakasa } 115241a519729505a877844f2c57a33509c302dddbceKen Wakasa 1153b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard // "ic" may be null 11548fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka private static void removeTrailingSpaceWhileInBatchEdit(final InputConnection ic) { 11559a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic == null) return; 1156b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard final CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 11579a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (lastOne != null && lastOne.length() == 1 1158571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastOne.charAt(0) == Keyboard.CODE_SPACE) { 11599a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.deleteSurroundingText(1, 0); 11609a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 11619a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 11629a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa 1163c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka @Override 1164923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean addWordToDictionary(String word) { 1165923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mUserDictionary.addWord(word, 128); 11666558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Suggestion strip should be updated after the operation of adding word to the 11676558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // user dictionary 1168d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1169923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1170923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1171923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 11728fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka private static boolean isAlphabet(int code) { 11738fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka return Character.isLetter(code); 1174923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1175a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1176e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka private void onSettingsKeyPressed() { 1177cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa if (isShowingOptionDialog()) return; 1178d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) { 1179d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka showSubtypeSelectorAndSettings(); 118023d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka } else if (Utils.hasMultipleEnabledIMEsOrSubtypes(false /* exclude aux subtypes */)) { 1181d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka showOptionsMenu(); 1182d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka } else { 1183d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka launchSettings(); 11849a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 11859a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 11869a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 1187cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa // Virtual codes representing custom requests. These are used in onCustomRequest() below. 1188cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa public static final int CODE_SHOW_INPUT_METHOD_PICKER = 1; 1189d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka public static final int CODE_HAPTIC_AND_AUDIO_FEEDBACK = 2; 1190cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa 1191cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa @Override 1192cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa public boolean onCustomRequest(int requestCode) { 1193cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa if (isShowingOptionDialog()) return false; 1194cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa switch (requestCode) { 1195cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa case CODE_SHOW_INPUT_METHOD_PICKER: 119623d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka if (Utils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */)) { 119779efbed76f638be298493107fa2d0cd1b5eb529esatok mImm.showInputMethodPicker(); 1198cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return true; 11999a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 1200cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return false; 1201d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka case CODE_HAPTIC_AND_AUDIO_FEEDBACK: 1202d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka hapticAndAudioFeedback(Keyboard.CODE_UNSPECIFIED); 1203d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka return true; 12049a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 1205cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return false; 12069a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 12079a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 12089a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok private boolean isShowingOptionDialog() { 12099a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok return mOptionsDialog != null && mOptionsDialog.isShowing(); 12109a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 12119a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 1212120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private void insertPunctuationFromSuggestionStrip(final InputConnection ic, final int code) { 1213120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final CharSequence beforeText = ic != null ? ic.getTextBeforeCursor(1, 0) : null; 1214120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final int toLeft = TextUtils.isEmpty(beforeText) ? 0 : beforeText.charAt(0); 1215120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final boolean shouldRegisterSwapPunctuation; 1216120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // If we have a space left of the cursor and it's a weak or a magic space, then we should 1217120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // swap it, and override the space state with SPACESTATE_SWAP_PUNCTUATION. 1218120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // To swap it, we fool handleSeparator to think the previous space state was a 1219120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // magic space. 12209de5cfc67a4e349c547e40678add27cdd6ca8490Jean Chalard if (Keyboard.CODE_SPACE == toLeft && mSpaceState == SPACE_STATE_WEAK 1221a8c8ab1cb4f148693ebf8443c62b029db0840d26Jean Chalard && mSettingsValues.isMagicSpaceSwapper(code)) { 1222120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_MAGIC; 1223120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard shouldRegisterSwapPunctuation = true; 1224120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } else { 1225120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard shouldRegisterSwapPunctuation = false; 1226120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1227120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard onCodeInput(code, new int[] { code }, 1228120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard KeyboardActionListener.NOT_A_TOUCH_COORDINATE, 1229120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard KeyboardActionListener.NOT_A_TOUCH_COORDINATE); 1230120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (shouldRegisterSwapPunctuation) { 1231120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_SWAP_PUNCTUATION; 1232120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1233126698fdd256a2e3734634d3b923cabd800064baJean Chalard } 1234126698fdd256a2e3734634d3b923cabd800064baJean Chalard 12355f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // Implementation of {@link KeyboardActionListener}. 12365a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 12378aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { 1238175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka final long when = SystemClock.uptimeMillis(); 1239571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) { 1240923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mDeleteCount = 0; 1241923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1242923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastKeyTime = when; 1243175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 1244120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // The space state depends only on the last character pressed and its own previous 1245120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // state. Here, we revert the space state to neutral if the key is actually modifying 1246120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // the input contents (any non-shift key), which is what we should do for 1247120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // all inputs that do not result in a special state. Each character handling is then 1248120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // free to override the state as they see fit. 1249120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final int spaceState = mSpaceState; 1250ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa 1251ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa // TODO: Consolidate the double space timer, mLastKeyTime, and the space state. 1252ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa if (primaryCode != Keyboard.CODE_SPACE) { 1253ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa mHandler.cancelDoubleSpacesTimer(); 1254ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa } 1255ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa 1256923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 1257571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_DELETE: 1258120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 1259120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard handleBackspace(spaceState); 12604189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka mDeleteCount++; 12614733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 12624189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka LatinImeLogger.logOnDelete(); 12634189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1264571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_SHIFT: 1265e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: 12662a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka // Shift and symbol key is handled in onPressKey() and onReleaseKey(). 12674189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1268e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SETTINGS: 126993246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka onSettingsKeyPressed(); 12704189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1271571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_CAPSLOCK: 12725731b939c7baa2ca64a59b35f48fb3c2a43ba739Tadashi G. Takaoka // Caps lock code is handled in KeyboardSwitcher.onCodeInput() below. 1273d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka hapticAndAudioFeedback(primaryCode); 12744189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1275d2c5fdda862f6dd2a1e020cf674c35fbbc63fc92Tadashi G. Takaoka case Keyboard.CODE_SHORTCUT: 127693246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka mSubtypeSwitcher.switchToShortcutIME(); 12774189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1278571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_TAB: 127945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka handleTab(); 12804733609947c0ec74e460bd714fffca0518ade93aJean Chalard // There are two cases for tab. Either we send a "next" event, that may change the 12814733609947c0ec74e460bd714fffca0518ade93aJean Chalard // focus but will never move the cursor. Or, we send a real tab keycode, which some 12824733609947c0ec74e460bd714fffca0518ade93aJean Chalard // applications may accept or ignore, and we don't know whether this will move the 12834733609947c0ec74e460bd714fffca0518ade93aJean Chalard // cursor or not. So actually, we don't really know. 12844733609947c0ec74e460bd714fffca0518ade93aJean Chalard // So to go with the safer option, we'd rather behave as if the user moved the 12854733609947c0ec74e460bd714fffca0518ade93aJean Chalard // cursor when they didn't than the opposite. We also expect that most applications 12864733609947c0ec74e460bd714fffca0518ade93aJean Chalard // will actually use tab only for focus movement. 12874733609947c0ec74e460bd714fffca0518ade93aJean Chalard // To sum it up: do not update mExpectingUpdateSelection here. 12884189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 12894189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka default: 1290120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 129117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.isWordSeparator(primaryCode)) { 1292120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard handleSeparator(primaryCode, x, y, spaceState); 12934189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } else { 1294120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard handleCharacter(primaryCode, keyCodes, x, y, spaceState); 12954189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 12964733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 12974733609947c0ec74e460bd714fffca0518ade93aJean Chalard break; 1298923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1299eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka switcher.onCodeInput(primaryCode); 1300dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Reset after any single keystroke 1301dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = null; 1302923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1303a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 13045a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 13058aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onTextInput(CharSequence text) { 1306b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.commitVoiceInput(); 13079351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1308923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 1309923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 131055b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka commitTyped(ic); 13119351550dc6af7859e5280e16144c9386a37b976dKen Wakasa maybeRemovePreviousPeriod(ic, text); 1312923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(text, 1); 1313923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1314b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 13158cab0b56eb8db311f158b18a361d9ceb85cff482Tadashi G. Takaoka mKeyboardSwitcher.onCodeInput(Keyboard.CODE_OUTPUT_TEXT); 1316120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 1317dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = text; 13189e8761c4402ddc11c942ed2e583bd7d58f70c5eaJean Chalard mWordComposer.reset(); 1319923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1320923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 13215a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 13228aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCancelInput() { 132383e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka // User released a finger outside any key 13245f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka mKeyboardSwitcher.onCancelInput(); 132583e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka } 132683e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka 1327120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private void handleBackspace(final int spaceState) { 1328b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok if (mVoiceProxy.logAndRevertVoiceInput()) return; 1329504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1330504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (ic == null) return; 1331979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.beginBatchEdit(); 1332a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard handleBackspaceWhileInBatchEdit(spaceState, ic); 1333a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard ic.endBatchEdit(); 1334a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard } 1335979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1336a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard // "ic" may not be null. 1337a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard private void handleBackspaceWhileInBatchEdit(final int spaceState, final InputConnection ic) { 1338b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleBackspace(); 13394f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 13402245c3b5b3691928b08fd6accf8d4a21fb35e26bJean Chalard // In many cases, we may have to put the keyboard in auto-shift state again. 13412245c3b5b3691928b08fd6accf8d4a21fb35e26bJean Chalard mHandler.postUpdateShiftKeyState(); 13422245c3b5b3691928b08fd6accf8d4a21fb35e26bJean Chalard 13435c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { 13445c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // Cancel multi-character input: remove the text we just entered. 13455c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // This is triggered on backspace after a key that inputs multiple characters, 13465c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // like the smiley key or the .com key. 13475c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard ic.deleteSurroundingText(mEnteredText.length(), 0); 13485c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // If we have mEnteredText, then we know that mHasUncommittedTypedChars == false. 13495c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // In addition we know that spaceState is false, and that we should not be 13505c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // reverting any autocorrect at this point. So we can safely return. 13515c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard return; 13525c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard } 13535c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard 1354196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (mWordComposer.isComposingWord()) { 13553651220327c051d8017045aa5e8919461507b3f8Jean Chalard final int length = mWordComposer.size(); 1356923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (length > 0) { 13579318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.deleteLast(); 135877d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); 1359196d82cdd740580ed79d801483dbc282be85d076Jean Chalard // If we have deleted the last remaining character of a word, then we are not 1360196d82cdd740580ed79d801483dbc282be85d076Jean Chalard // isComposingWord() any more. 1361196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (!mWordComposer.isComposingWord()) { 1362196d82cdd740580ed79d801483dbc282be85d076Jean Chalard // Not composing word any more, so we can show bigrams. 1363cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.postUpdateBigramPredictions(); 136489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 1365196d82cdd740580ed79d801483dbc282be85d076Jean Chalard // Still composing a word, so we still have letters to deduce a suggestion from. 136689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.postUpdateSuggestions(); 136789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 1368923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1369923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(1, 0); 1370923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1371890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard } else { 137272d285f4d758dd1ceafb7d9bd3dd330efd24c1f8Jean Chalard // We should be very careful about auto-correction cancellation and suggestion 137372d285f4d758dd1ceafb7d9bd3dd330efd24c1f8Jean Chalard // resuming here. The behavior needs to be different according to text field types, 137472d285f4d758dd1ceafb7d9bd3dd330efd24c1f8Jean Chalard // and it would be much clearer to test for them explicitly here rather than 137572d285f4d758dd1ceafb7d9bd3dd330efd24c1f8Jean Chalard // relying on implicit values like "whether the suggestion strip is displayed". 13769e8761c4402ddc11c942ed2e583bd7d58f70c5eaJean Chalard if (mWordComposer.didAutoCorrectToAnotherWord()) { 1377d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard Utils.Stats.onAutoCorrectionCancellation(); 1378d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard cancelAutoCorrect(ic); 1379120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return; 1380120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1381d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard 1382d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard if (SPACE_STATE_DOUBLE == spaceState) { 1383d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard if (revertDoubleSpace(ic)) { 1384d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard // No need to reset mSpaceState, it has already be done (that's why we 1385d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard // receive it as a parameter) 1386d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard return; 1387d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard } 1388d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard } else if (SPACE_STATE_SWAP_PUNCTUATION == spaceState) { 1389d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard if (revertSwapPunctuation(ic)) { 1390d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard // Likewise 1391d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard return; 1392d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard } 13934733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 1394504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka 139572d285f4d758dd1ceafb7d9bd3dd330efd24c1f8Jean Chalard // See the comment above: must be careful about resuming auto-suggestion. 1396913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) { 13976558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Go back to the suggestion mode if the user canceled the 139855b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // "Touch again to save". 1399a8ba49c2534220105ce302a50b3a9ddaf831ef20Jean Chalard // NOTE: In general, we don't revert the word when backspacing 14006558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // from a manual suggestion pick. We deliberately chose a 14016558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // different behavior only in the case of picking the first 14026558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // suggestion (typed word). It's intentional to have made this 14036558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // inconsistent with backspacing after selecting other suggestions. 1404890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard restartSuggestionsOnManuallyPickedTypedWord(ic); 14056558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } else { 140677da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard // Here we must check whether there is a selection. If so we should remove the 140777da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard // selected text, otherwise we should just delete the character before the cursor. 140877da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard if (mLastSelectionStart != mLastSelectionEnd) { 140977da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard final int lengthToDelete = mLastSelectionEnd - mLastSelectionStart; 141077da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard ic.setSelection(mLastSelectionEnd, mLastSelectionEnd); 141177da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard ic.deleteSurroundingText(lengthToDelete, 0); 141277da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard } else { 141377da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard if (NOT_A_CURSOR_POSITION == mLastSelectionEnd) { 141477da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard // We don't know whether there is a selection or not. We just send a false 141577da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard // hardware key event and let TextView sort it out for us. The problem 141677da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard // here is, this is asynchronous with respect to the input connection 141777da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard // batch edit, so it may flicker. But this only ever happens if backspace 141877da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard // is pressed just after the IME is invoked, and then again only once. 141977da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard // TODO: add an API call that gets the selection indices. This is available 142077da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard // to the IME in the general case via onUpdateSelection anyway, and would 142177da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard // allow us to remove this race condition. 142277da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 142377da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard } else { 142477da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard ic.deleteSurroundingText(1, 0); 142577da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard } 142677da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard if (mDeleteCount > DELETE_ACCELERATE_AT) { 142777da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard ic.deleteSurroundingText(1, 0); 142877da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard } 14296558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 1430edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard if (isSuggestionsRequested()) { 1431edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard restartSuggestionsOnWordBeforeCursorIfAtEndOfWord(ic); 1432edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard } 1433923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1434923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1435923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1436923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 143745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka private void handleTab() { 143845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final int imeOptions = getCurrentInputEditorInfo().imeOptions; 1439b2707856aba4fc9b063f26305f1fb603b19c1701satok if (!EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) 1440b2707856aba4fc9b063f26305f1fb603b19c1701satok && !EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions)) { 144145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB); 144245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka return; 144345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 144445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 144545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 144645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (ic == null) 144745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka return; 144845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 144945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka // True if keyboard is in either chording shift or manual temporary upper case mode. 145045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final boolean isManualTemporaryUpperCase = mKeyboardSwitcher.isManualTemporaryUpperCase(); 1451b2707856aba4fc9b063f26305f1fb603b19c1701satok if (EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) 145245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka && !isManualTemporaryUpperCase) { 1453b2707856aba4fc9b063f26305f1fb603b19c1701satok EditorInfoCompatUtils.performEditorActionNext(ic); 1454b2707856aba4fc9b063f26305f1fb603b19c1701satok } else if (EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions) 145545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka && isManualTemporaryUpperCase) { 1456b2707856aba4fc9b063f26305f1fb603b19c1701satok EditorInfoCompatUtils.performEditorActionPrevious(ic); 145745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 145845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 145945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 1460120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private void handleCharacter(final int primaryCode, final int[] keyCodes, final int x, 1461120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final int y, final int spaceState) { 1462b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleCharacter(); 1463b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard final InputConnection ic = getCurrentInputConnection(); 1464dafa7a8e15447544842975047f831883e67700c5Jean Chalard if (null != ic) ic.beginBatchEdit(); 1465dafa7a8e15447544842975047f831883e67700c5Jean Chalard // TODO: if ic is null, does it make any sense to call this? 1466dafa7a8e15447544842975047f831883e67700c5Jean Chalard handleCharacterWhileInBatchEdit(primaryCode, keyCodes, x, y, spaceState, ic); 1467dafa7a8e15447544842975047f831883e67700c5Jean Chalard if (null != ic) ic.endBatchEdit(); 1468dafa7a8e15447544842975047f831883e67700c5Jean Chalard } 1469dafa7a8e15447544842975047f831883e67700c5Jean Chalard 1470dafa7a8e15447544842975047f831883e67700c5Jean Chalard // "ic" may be null without this crashing, but the behavior will be really strange 1471dafa7a8e15447544842975047f831883e67700c5Jean Chalard private void handleCharacterWhileInBatchEdit(final int primaryCode, final int[] keyCodes, 1472dafa7a8e15447544842975047f831883e67700c5Jean Chalard final int x, final int y, final int spaceState, final InputConnection ic) { 1473120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (SPACE_STATE_MAGIC == spaceState 1474126698fdd256a2e3734634d3b923cabd800064baJean Chalard && mSettingsValues.isMagicSpaceStripper(primaryCode)) { 1475dafa7a8e15447544842975047f831883e67700c5Jean Chalard if (null != ic) removeTrailingSpaceWhileInBatchEdit(ic); 14760730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard } 14770730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard 1478196d82cdd740580ed79d801483dbc282be85d076Jean Chalard boolean isComposingWord = mWordComposer.isComposingWord(); 1479e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka int code = primaryCode; 14803889462439357fd76c0b82dfd52e1ca6e0bafd2dKen Wakasa if ((isAlphabet(code) || mSettingsValues.isSymbolExcludedFromWordSeparators(code)) 14813889462439357fd76c0b82dfd52e1ca6e0bafd2dKen Wakasa && isSuggestionsRequested() && !isCursorTouchingWord()) { 14827b5bc1ff4d4694045e69e6aff8a2b5365ff882d1Jean Chalard if (!isComposingWord) { 14836d1cbbc2ffb9d7046189174ec68b5b72bbc154b3Jean Chalard // Reset entirely the composing state anyway, then start composing a new word unless 14847b5bc1ff4d4694045e69e6aff8a2b5365ff882d1Jean Chalard // the character is a single quote. The idea here is, single quote is not a 14857b5bc1ff4d4694045e69e6aff8a2b5365ff882d1Jean Chalard // separator and it should be treated as a normal character, except in the first 14867b5bc1ff4d4694045e69e6aff8a2b5365ff882d1Jean Chalard // position where it should not start composing a word. 14877b5bc1ff4d4694045e69e6aff8a2b5365ff882d1Jean Chalard isComposingWord = (Keyboard.CODE_SINGLE_QUOTE != code); 14889318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.reset(); 14897e99a28dfcc14f5b19220442db972ca8d786b4feKen Wakasa clearSuggestions(); 1490604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.onFinishComposingText(); 1491923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1492923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 149335f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 1494f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (switcher.isShiftedOrShiftLocked()) { 1495eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT 1496eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani || keyCodes[0] > Character.MAX_CODE_POINT) { 1497eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani return; 1498eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani } 1499e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka code = keyCodes[0]; 1500e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (switcher.isAlphabetMode() && Character.isLowerCase(code)) { 150135f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka // In some locales, such as Turkish, Character.toUpperCase() may return a wrong 150235f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka // character because it doesn't take care of locale. 150335f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka final String upperCaseString = new String(new int[] {code}, 0, 1) 150435f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka .toUpperCase(mSubtypeSwitcher.getInputLocale()); 150535f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka if (upperCaseString.codePointCount(0, upperCaseString.length()) == 1) { 150635f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka code = upperCaseString.codePointAt(0); 150712a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka } else { 150812a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka // Some keys, such as [eszett], have upper case as multi-characters. 150935f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka onTextInput(upperCaseString); 151012a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka return; 151112a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka } 1512979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1513923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 15147b5bc1ff4d4694045e69e6aff8a2b5365ff882d1Jean Chalard if (isComposingWord) { 15159318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.add(code, keyCodes, x, y); 1516923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 15171c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani // If it's the first letter, make note of auto-caps state 15189318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa if (mWordComposer.size() == 1) { 15199318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.setAutoCapitalized(getCurrentAutoCapsState()); 1520604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.onStartComposingText(); 15211c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 152277d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); 1523923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1524d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1525923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1526e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka sendKeyChar((char)code); 1527923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1528120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (SPACE_STATE_MAGIC == spaceState 1529126698fdd256a2e3734634d3b923cabd800064baJean Chalard && mSettingsValues.isMagicSpaceSwapper(primaryCode)) { 1530b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard if (null != ic) swapSwapperAndSpaceWhileInBatchEdit(ic); 1531863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } 1532863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard 1533406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard if (mSettingsValues.isWordSeparator(code)) { 1534406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard Utils.Stats.onSeparator((char)code, x, y); 1535406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard } else { 1536406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard Utils.Stats.onNonSeparator((char)code, x, y); 1537406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard } 1538923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1539923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1540120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private void handleSeparator(final int primaryCode, final int x, final int y, 1541120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final int spaceState) { 1542b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleSeparator(); 1543604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.onFinishComposingText(); 15444f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 154555b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // Should dismiss the "Touch again to save" message when handling separator 1546913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) { 1547cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.cancelUpdateBigramPredictions(); 1548d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 15496558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 15506558253160e2039c87f424bd814f402ecd31de3bKen Wakasa 1551923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Handle separator 15521b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1553923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1554923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 1555923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1556196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (mWordComposer.isComposingWord()) { 1557923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In certain languages where single quote is a separator, it's better 1558a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker // not to auto correct, but accept the typed word. For instance, 1559923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // in Italian dov' should not be expanded to dove' because the elision 1560923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // requires the last vowel to be removed. 1561f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled 1562dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard && !mInputAttributes.mInputTypeNoAutoCorrect; 156317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (shouldAutoCorrect && primaryCode != Keyboard.CODE_SINGLE_QUOTE) { 1564f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard commitCurrentAutoCorrection(primaryCode, ic); 1565923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1566923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project commitTyped(ic); 1567923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1568923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 15694ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1570120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final boolean swapMagicSpace; 15712c77216e22e5f9d1d2191ce577f2707bea5b815aJean Chalard if (Keyboard.CODE_ENTER == primaryCode && (SPACE_STATE_MAGIC == spaceState 15722c77216e22e5f9d1d2191ce577f2707bea5b815aJean Chalard || SPACE_STATE_SWAP_PUNCTUATION == spaceState)) { 15732c77216e22e5f9d1d2191ce577f2707bea5b815aJean Chalard removeTrailingSpaceWhileInBatchEdit(ic); 15742c77216e22e5f9d1d2191ce577f2707bea5b815aJean Chalard swapMagicSpace = false; 15752c77216e22e5f9d1d2191ce577f2707bea5b815aJean Chalard } else if (SPACE_STATE_MAGIC == spaceState) { 157617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.isMagicSpaceSwapper(primaryCode)) { 1577120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard swapMagicSpace = true; 1578863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } else { 1579120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard swapMagicSpace = false; 1580b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard if (mSettingsValues.isMagicSpaceStripper(primaryCode)) { 1581b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard removeTrailingSpaceWhileInBatchEdit(ic); 1582b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard } 1583863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } 15840730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard } else { 1585120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard swapMagicSpace = false; 1586863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } 1587863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard 1588120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard sendKeyChar((char)primaryCode); 158989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 159089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (Keyboard.CODE_SPACE == primaryCode) { 1591120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (isSuggestionsRequested()) { 1592120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (maybeDoubleSpaceWhileInBatchEdit(ic)) { 1593120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_DOUBLE; 1594120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } else if (!isShowingPunctuationList()) { 1595120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_WEAK; 1596120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1597126698fdd256a2e3734634d3b923cabd800064baJean Chalard } 1598120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 1599120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mHandler.startDoubleSpacesTimer(); 160089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (!isCursorTouchingWord()) { 160189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.cancelUpdateSuggestions(); 1602cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.postUpdateBigramPredictions(); 160389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 160489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 1605120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (swapMagicSpace) { 1606120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard swapSwapperAndSpaceWhileInBatchEdit(ic); 1607120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_MAGIC; 1608120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1609120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 161089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Set punctuation right away. onUpdateSelection will fire but tests whether it is 161189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // already displayed or not, so it's okay. 161255b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka setPunctuationSuggestions(); 1613923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1614120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 1615406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard Utils.Stats.onSeparator((char)primaryCode, x, y); 1616120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 1617923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1618923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1619923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1620923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1621466741d8a78965b8509bf527344f289e50873092Mike LeBeau 162277d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard private CharSequence getTextWithUnderline(final CharSequence text) { 162377d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard return mComposingStateManager.isAutoCorrectionIndicatorOn() 162477d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(this, text) 162577d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard : mWordComposer.getTypedWord(); 162677d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard } 162777d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard 1628923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleClose() { 1629923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project commitTyped(getCurrentInputConnection()); 1630b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleClose(); 1631923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project requestHideSelf(0); 1632c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 16331679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka if (inputView != null) 16341679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka inputView.closing(); 1635923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1636923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 16377a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isSuggestionsRequested() { 1638dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard return mInputAttributes.mIsSettingsSuggestionStripOn 1639c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka && (mCorrectionMode > 0 || isShowingSuggestionsStrip()); 1640923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1641a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 16427a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isShowingPunctuationList() { 1643cb8cb95d0afd340de9f1a0e15948f0068d2450bcKen Wakasa if (mSuggestionsView == null) return false; 1644913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka return mSettingsValues.mSuggestPuncList == mSuggestionsView.getSuggestions(); 16457599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 16467599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 16477a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isShowingSuggestionsStrip() { 16487599cfea4a2d56f4779452ec8e8742f7b9629cc0satok return (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_VALUE) 16497599cfea4a2d56f4779452ec8e8742f7b9629cc0satok || (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 165038f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka && mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT); 16517599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 16527599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 1653913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka public boolean isSuggestionsStripVisible() { 1654913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView == null) 1655b5e00d5841b946de8970875231456228ae0eb6b1Ken Wakasa return false; 1656d0c5f9395a1b94e8425982e353d090f972dc44f0Jean Chalard if (mSuggestionsView.isShowingAddToDictionaryHint()) 16579fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 16589fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!isShowingSuggestionsStrip()) 16599fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return false; 1660dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard if (mInputAttributes.mApplicationSpecifiedCompletionOn) 16619fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 16629fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return isSuggestionsRequested(); 1663923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1664923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1665409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void switchToKeyboardView() { 1666060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (DEBUG) { 1667060efb6d82af1f896d90cb845c8ae07c726f85e1satok Log.d(TAG, "Switch to keyboard view."); 1668060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 1669c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka View v = mKeyboardSwitcher.getKeyboardView(); 1670060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (v != null) { 1671060efb6d82af1f896d90cb845c8ae07c726f85e1satok // Confirms that the keyboard view doesn't have parent view. 1672060efb6d82af1f896d90cb845c8ae07c726f85e1satok ViewParent p = v.getParent(); 1673060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (p != null && p instanceof ViewGroup) { 1674060efb6d82af1f896d90cb845c8ae07c726f85e1satok ((ViewGroup) p).removeView(v); 16755a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } 1676060efb6d82af1f896d90cb845c8ae07c726f85e1satok setInputView(v); 1677060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 1678913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShown(isSuggestionsStripVisible()); 1679060efb6d82af1f896d90cb845c8ae07c726f85e1satok updateInputViewShown(); 1680060efb6d82af1f896d90cb845c8ae07c726f85e1satok mHandler.postUpdateSuggestions(); 1681466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1682466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1683409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void clearSuggestions() { 16847e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(SuggestedWords.EMPTY); 1685466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1686466741d8a78965b8509bf527344f289e50873092Mike LeBeau 16877e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka public void setSuggestions(SuggestedWords words) { 1688913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) { 1689913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.setSuggestions(words); 16905e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka mKeyboardSwitcher.onAutoCorrectionStateChanged( 16915e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka words.hasWordAboveAutoCorrectionScoreThreshold()); 1692466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1693ec780e2868962bf17f0dfd35d36895f543bde40asatok 1694ec780e2868962bf17f0dfd35d36895f543bde40asatok // Put a blue underline to a word in TextView which will be auto-corrected. 1695ec780e2868962bf17f0dfd35d36895f543bde40asatok final InputConnection ic = getCurrentInputConnection(); 1696604d80c67185954d4691ac775be59c499eee3b1csatok if (ic != null) { 1697604d80c67185954d4691ac775be59c499eee3b1csatok final boolean oldAutoCorrectionIndicator = 1698604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.isAutoCorrectionIndicatorOn(); 1699604d80c67185954d4691ac775be59c499eee3b1csatok final boolean newAutoCorrectionIndicator = Utils.willAutoCorrect(words); 1700604d80c67185954d4691ac775be59c499eee3b1csatok if (oldAutoCorrectionIndicator != newAutoCorrectionIndicator) { 170177d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard mComposingStateManager.setAutoCorrectionIndicatorOn(newAutoCorrectionIndicator); 170277d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard if (DEBUG) { 1703fe2d90798ea409ee39d6f63942eb01bb7eed98e3satok Log.d(TAG, "Flip the indicator. " + oldAutoCorrectionIndicator 1704fe2d90798ea409ee39d6f63942eb01bb7eed98e3satok + " -> " + newAutoCorrectionIndicator); 17050bfe359ee42af9c4487ce56acf42c74a2510980dJean Chalard if (mComposingStateManager.isComposing() && newAutoCorrectionIndicator 170677d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard != mComposingStateManager.isAutoCorrectionIndicatorOn()) { 17070bfe359ee42af9c4487ce56acf42c74a2510980dJean Chalard throw new RuntimeException("Couldn't flip the indicator!"); 170877d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard } 1709fe2d90798ea409ee39d6f63942eb01bb7eed98e3satok } 171077d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard final CharSequence textWithUnderline = 171177d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard getTextWithUnderline(mWordComposer.getTypedWord()); 1712604d80c67185954d4691ac775be59c499eee3b1csatok if (!TextUtils.isEmpty(textWithUnderline)) { 1713604d80c67185954d4691ac775be59c499eee3b1csatok ic.setComposingText(textWithUnderline, 1); 1714604d80c67185954d4691ac775be59c499eee3b1csatok } 1715ec780e2868962bf17f0dfd35d36895f543bde40asatok } 1716ec780e2868962bf17f0dfd35d36895f543bde40asatok } 1717466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1718466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1719409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void updateSuggestions() { 1720923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Check if we have a suggestion engine attached. 17219fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if ((mSuggest == null || !isSuggestionsRequested()) 1722b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok && !mVoiceProxy.isVoiceInputHighlighted()) { 1723edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard if (mWordComposer.isComposingWord()) { 1724edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard Log.w(TAG, "Called updateSuggestions but suggestions were not requested!"); 1725edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard mWordComposer.setAutoCorrection(mWordComposer.getTypedWord()); 1726edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard } 1727923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1728923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1729466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1730cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard mHandler.cancelUpdateSuggestions(); 1731cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard mHandler.cancelUpdateBigramPredictions(); 1732cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard 1733196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (!mWordComposer.isComposingWord()) { 1734ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setPunctuationSuggestions(); 1735923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1736923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1737979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 17389f67e12a0e3f77985fb8bafe0db4c00e32317b9asatok // TODO: May need a better way of retrieving previous word 173940f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final InputConnection ic = getCurrentInputConnection(); 174040f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final CharSequence prevWord; 174140f7efc172928bdd6048e91421a766abe5b22996Jean Chalard if (null == ic) { 174240f7efc172928bdd6048e91421a766abe5b22996Jean Chalard prevWord = null; 174340f7efc172928bdd6048e91421a766abe5b22996Jean Chalard } else { 174440f7efc172928bdd6048e91421a766abe5b22996Jean Chalard prevWord = EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators); 174540f7efc172928bdd6048e91421a766abe5b22996Jean Chalard } 174640f7efc172928bdd6048e91421a766abe5b22996Jean Chalard // getSuggestedWordBuilder handles gracefully a null value of prevWord 1747f7d6517d6b1a1dd88e2142e1a15703bb839be01bJean Chalard final SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(mWordComposer, 17483708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(), mCorrectionMode); 1749923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1750dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard boolean autoCorrectionAvailable = !mInputAttributes.mInputTypeNoAutoCorrect 1751dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard && mSuggest.hasAutoCorrection(); 1752f7d6517d6b1a1dd88e2142e1a15703bb839be01bJean Chalard final CharSequence typedWord = mWordComposer.getTypedWord(); 1753bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // Here, we want to promote a whitelisted word if exists. 17545f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard // TODO: Change this scheme - a boolean is not enough. A whitelisted word may be "valid" 17555f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard // but still autocorrected from - in the case the whitelist only capitalizes the word. 17565f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard // The whitelist should be case-insensitive, so it's not possible to be consistent with 17575f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard // a boolean flag. Right now this is handled with a slight hack in 17585f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard // WhitelistDictionary#shouldForciblyAutoCorrectFrom. 1759f7d6517d6b1a1dd88e2142e1a15703bb839be01bJean Chalard final int quotesCount = mWordComposer.trailingSingleQuotesCount(); 17605f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard final boolean allowsToBeAutoCorrected = AutoCorrection.allowsToBeAutoCorrected( 1761c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard mSuggest.getUnigramDictionaries(), 1762c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard // If the typed string ends with a single quote, for dictionary lookup purposes 1763c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard // we behave as if the single quote was not here. Here, we are looking up the 1764c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard // typed string in the dictionary (to avoid autocorrecting from an existing 1765c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard // word, so for consistency this lookup should be made WITHOUT the trailing 1766c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard // single quote. 1767117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard quotesCount > 0 1768117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard ? typedWord.subSequence(0, typedWord.length() - quotesCount) : typedWord, 1769c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard preferCapitalization()); 1770979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mCorrectionMode == Suggest.CORRECTION_FULL 1771979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { 17725f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard autoCorrectionAvailable |= (!allowsToBeAutoCorrected); 1773923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 17744a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani // Don't auto-correct words with multiple capital letter 1775f7d6517d6b1a1dd88e2142e1a15703bb839be01bJean Chalard autoCorrectionAvailable &= !mWordComposer.isMostlyCaps(); 1776979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1777a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // Basically, we update the suggestion strip only when suggestion count > 1. However, 1778a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // there is an exception: We update the suggestion strip whenever typed word's length 1779f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // is 1 or typed word is found in dictionary, regardless of suggestion count. Actually, 1780f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // in most cases, suggestion count is 1 when typed word's length is 1, but we do always 1781f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // need to clear the previous state when the user starts typing a word (i.e. typed word's 1782f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // length == 1). 1783fe1a6d961cf039357f061482461e4d2e951ad346satok if (typedWord != null) { 17845f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard if (builder.size() > 1 || typedWord.length() == 1 || (!allowsToBeAutoCorrected) 1785913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka || mSuggestionsView.isShowingAddToDictionaryHint()) { 17865f41b705fc95b21c8edd6226bb50c0fa78a39261Jean Chalard builder.setTypedWordValid(!allowsToBeAutoCorrected).setHasMinimalSuggestion( 17878558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa autoCorrectionAvailable); 1788fe1a6d961cf039357f061482461e4d2e951ad346satok } else { 1789074cda4d266b5d034d4348961c9183e32b16af5asatok SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions(); 1790074cda4d266b5d034d4348961c9183e32b16af5asatok if (previousSuggestions == mSettingsValues.mSuggestPuncList) { 1791074cda4d266b5d034d4348961c9183e32b16af5asatok if (builder.size() == 0) { 1792074cda4d266b5d034d4348961c9183e32b16af5asatok return; 1793074cda4d266b5d034d4348961c9183e32b16af5asatok } 1794074cda4d266b5d034d4348961c9183e32b16af5asatok previousSuggestions = SuggestedWords.EMPTY; 1795074cda4d266b5d034d4348961c9183e32b16af5asatok } 1796fe1a6d961cf039357f061482461e4d2e951ad346satok builder.addTypedWordAndPreviousSuggestions(typedWord, previousSuggestions); 1797fe1a6d961cf039357f061482461e4d2e951ad346satok } 17989fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka } 17997e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka showSuggestions(builder.build(), typedWord); 1800979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 18014a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani 18029fbfd5877305ed19a20663630b498b6b3fdae942satok public void showSuggestions(SuggestedWords suggestedWords, CharSequence typedWord) { 18032aa1dd45c44295e2f7e8ece1b520032d86b9f908satok final boolean shouldBlockAutoCorrectionBySafetyNet = 18042aa1dd45c44295e2f7e8ece1b520032d86b9f908satok Utils.shouldBlockAutoCorrectionBySafetyNet(suggestedWords, mSuggest); 18052aa1dd45c44295e2f7e8ece1b520032d86b9f908satok if (shouldBlockAutoCorrectionBySafetyNet) { 18062aa1dd45c44295e2f7e8ece1b520032d86b9f908satok suggestedWords.setShouldBlockAutoCorrection(); 18072aa1dd45c44295e2f7e8ece1b520032d86b9f908satok } 18087e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(suggestedWords); 18097e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka if (suggestedWords.size() > 0) { 18102aa1dd45c44295e2f7e8ece1b520032d86b9f908satok if (shouldBlockAutoCorrectionBySafetyNet) { 1811117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard mWordComposer.setAutoCorrection(typedWord); 181282411d47ba7e8133ed2390c6920945e139a738cesatok } else if (suggestedWords.hasAutoCorrectionWord()) { 1813117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard mWordComposer.setAutoCorrection(suggestedWords.getWord(1)); 1814923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1815117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard mWordComposer.setAutoCorrection(typedWord); 1816923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1817923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1818117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard // TODO: replace with mWordComposer.deleteAutoCorrection()? 1819117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard mWordComposer.setAutoCorrection(null); 1820923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1821913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShown(isSuggestionsStripVisible()); 1822923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1823923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1824f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard private void commitCurrentAutoCorrection(final int separatorCodePoint, 1825f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard final InputConnection ic) { 1826913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka // Complete any pending suggestions query first 1827d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka if (mHandler.hasPendingUpdateSuggestions()) { 1828d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 1829923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 1830923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1831117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard final CharSequence autoCorrection = mWordComposer.getAutoCorrectionOrNull(); 1832117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard if (autoCorrection != null) { 1833117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard final String typedWord = mWordComposer.getTypedWord(); 183446798d8f1f3d9012433d000790ba30ba910c0fa0Jean Chalard if (TextUtils.isEmpty(typedWord)) { 183546798d8f1f3d9012433d000790ba30ba910c0fa0Jean Chalard throw new RuntimeException("We have an auto-correction but the typed word " 183646798d8f1f3d9012433d000790ba30ba910c0fa0Jean Chalard + "is empty? Impossible! I must commit suicide."); 183746798d8f1f3d9012433d000790ba30ba910c0fa0Jean Chalard } 1838f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard Utils.Stats.onAutoCorrection(typedWord, autoCorrection.toString(), separatorCodePoint); 18394733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 18400fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard commitChosenWord(autoCorrection, WordComposer.COMMIT_TYPE_DECIDED_WORD); 1841f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard // Add the word to the user unigram dictionary if it's not a known word 1842117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard addToUserUnigramAndBigramDictionaries(autoCorrection, 1843f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard UserUnigramDictionary.FREQUENCY_FOR_TYPED); 1844f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard if (!typedWord.equals(autoCorrection) && null != ic) { 18451c6cf26c3705e845418a29718c034598b52293ccJean Chalard // This will make the correction flash for a short while as a visual clue 18461c6cf26c3705e845418a29718c034598b52293ccJean Chalard // to the user that auto-correction happened. 18471c6cf26c3705e845418a29718c034598b52293ccJean Chalard InputConnectionCompatUtils.commitCorrection(ic, 18481c6cf26c3705e845418a29718c034598b52293ccJean Chalard mLastSelectionEnd - typedWord.length(), typedWord, autoCorrection); 18491c6cf26c3705e845418a29718c034598b52293ccJean Chalard } 1850923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1851923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1852923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1853c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka @Override 1854923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void pickSuggestionManually(int index, CharSequence suggestion) { 1855604d80c67185954d4691ac775be59c499eee3b1csatok mComposingStateManager.onFinishComposingText(); 1856913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka SuggestedWords suggestions = mSuggestionsView.getSuggestions(); 185717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mVoiceProxy.flushAndLogAllTextModificationCounters(index, suggestion, 185817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mWordSeparators); 18594f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 18609351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 18619a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 18629a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.beginBatchEdit(); 18639a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1864dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard if (mInputAttributes.mApplicationSpecifiedCompletionOn 1865dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard && mApplicationSpecifiedCompletions != null 18661b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka && index >= 0 && index < mApplicationSpecifiedCompletions.length) { 1867923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 18689351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index]; 18699351550dc6af7859e5280e16144c9386a37b976dKen Wakasa ic.commitCompletion(completionInfo); 1870923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1871913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) { 1872913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.clear(); 1873923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1874b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 18759a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 18769a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 18779a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1878923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1879923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 18806a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 18816a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani // If this is a punctuation, apply it through the normal key press 188217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (suggestion.length() == 1 && (mSettingsValues.isWordSeparator(suggestion.charAt(0)) 188317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard || mSettingsValues.isSuggestedPunctuation(suggestion.charAt(0)))) { 1884979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Word separators are suggested before the user inputs something. 1885979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // So, LatinImeLogger logs "" as a user's input. 1886979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.logOnManualSuggestion( 18877e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka "", suggestion.toString(), index, suggestions.mWords); 1888863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // Find out whether the previous character is a space. If it is, as a special case 1889120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // for punctuation entered through the suggestion strip, it should be swapped 1890120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // if it was a magic or a weak space. This is meant to help in case the user 1891863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // pressed space on purpose of displaying the suggestion strip punctuation. 189283ffff2a49beeb41874b7cb40819a75001f708e2Ken Wakasa final int rawPrimaryCode = suggestion.charAt(0); 189383ffff2a49beeb41874b7cb40819a75001f708e2Ken Wakasa // Maybe apply the "bidi mirrored" conversions for parentheses 18943708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); 189549426a1ea941c0331a6e573e36cff3c3a8e8849cTadashi G. Takaoka final boolean isRtl = keyboard != null && keyboard.mIsRtlKeyboard; 189649426a1ea941c0331a6e573e36cff3c3a8e8849cTadashi G. Takaoka final int primaryCode = Key.getRtlParenthesisCode(rawPrimaryCode, isRtl); 189783ffff2a49beeb41874b7cb40819a75001f708e2Ken Wakasa 1898120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard insertPunctuationFromSuggestionStrip(ic, primaryCode); 1899120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // TODO: the following endBatchEdit seems useless, check 19009a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 19019a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 19029a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 19036a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani return; 19046a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 1905af9fe5c5fcad1db22f605e0568c9a77cef178d22Jean Chalard // We need to log before we commit, because the word composer will store away the user 1906af9fe5c5fcad1db22f605e0568c9a77cef178d22Jean Chalard // typed word. 1907af9fe5c5fcad1db22f605e0568c9a77cef178d22Jean Chalard LatinImeLogger.logOnManualSuggestion(mWordComposer.getTypedWord().toString(), 1908af9fe5c5fcad1db22f605e0568c9a77cef178d22Jean Chalard suggestion.toString(), index, suggestions.mWords); 19094733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 19100fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard commitChosenWord(suggestion, WordComposer.COMMIT_TYPE_MANUAL_PICK); 19119468335a06d2b0e3ef15f4f57f8c1b0857b34ebeAmith Yamasani // Add the word to the auto dictionary if it's not a known word 19120c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani if (index == 0) { 1913f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard addToUserUnigramAndBigramDictionaries(suggestion, 1914f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard UserUnigramDictionary.FREQUENCY_FOR_PICKED); 1915979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 1916bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok addToOnlyBigramDictionary(suggestion, 1); 19170c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani } 1918923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Follow it with a space 1919dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard if (mInputAttributes.mInsertSpaceOnPickSuggestionManually) { 19200730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard sendMagicSpace(); 1921923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1922979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1923c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // We should show the "Touch again to save" hint if the user pressed the first entry 1924c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // AND either: 19257f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is no dictionary (we know that because we tried to load it => null != mSuggest 1926c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // AND mSuggest.hasMainDictionary() is false) 19277f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is a dictionary and the word is not in it 19287f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // Please note that if mSuggest is null, it means that everything is off: suggestion 19297f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // and correction, so we shouldn't try to show the hint 19307f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // We used to look at mCorrectionMode here, but showing the hint should have nothing 19317f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // to do with the autocorrection setting. 1932bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean showingAddToDictionaryHint = index == 0 && mSuggest != null 1933bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // If there is no dictionary the hint should be shown. 1934c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa && (!mSuggest.hasMainDictionary() 1935bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // If "suggestion" is not in the dictionary, the hint should be shown. 1936bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok || !AutoCorrection.isValidWord( 1937bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok mSuggest.getUnigramDictionaries(), suggestion, true)); 1938b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani 1939406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard Utils.Stats.onSeparator((char)Keyboard.CODE_SPACE, WordComposer.NOT_A_COORDINATE, 1940406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard WordComposer.NOT_A_COORDINATE); 1941777118a40a363ccab69a00016d3156066513cb78Jean Chalard if (!showingAddToDictionaryHint) { 1942364da8c618303a7764595d2c15ee034a7671365dKen Wakasa // If we're not showing the "Touch again to save", then show corrections again. 1943979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // In case the cursor position doesn't change, make sure we show the suggestions again. 194441ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard updateBigramPredictions(); 194541ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // Updating the predictions right away may be slow and feel unresponsive on slower 194641ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // terminals. On the other hand if we just postUpdateBigramPredictions() it will 194741ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // take a noticeable delay to update them which may feel uneasy. 194895a6e58ebcd8f44b970a8238cf30e48b10fc4b61Jean Chalard } else { 194988562bec54658840dcce352127bdc15705c20a89Jean Chalard if (mIsUserDictionaryAvailable) { 1950644d33d60ea5a87501274488013d65f55238895eKen Wakasa mSuggestionsView.showAddToDictionaryHint( 1951644d33d60ea5a87501274488013d65f55238895eKen Wakasa suggestion, mSettingsValues.mHintToSaveText); 1952ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka } else { 1953ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1954ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka } 195566a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani } 19569a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 19579a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 19589a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1959923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1960a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1961979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 19628558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa * Commits the chosen word to the text field and saves it for later retrieval. 1963979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 19640fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard private void commitChosenWord(final CharSequence bestWord, final int commitType) { 19659351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1966923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 19671fef530ec7626fa16777f52b48191e61db8f46d4satok mVoiceProxy.rememberReplacedWord(bestWord, mSettingsValues.mWordSeparators); 19681531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard if (mSettingsValues.mEnableSuggestionSpanInsertion) { 19691531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions(); 19701531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan( 19711531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard this, bestWord, suggestedWords), 1); 19721531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard } else { 19731531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard ic.commitText(bestWord, 1); 19741531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard } 1975923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 19760fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard // TODO: figure out here if this is an auto-correct or if the best word is actually 19770fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard // what user typed. Note: currently this is done much later in 19780fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard // WordComposer#didAutoCorrectToAnotherWord by string equality of the remembered 19790fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard // strings. 19800fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard mWordComposer.onCommitWord(commitType); 1981923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1982923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 198389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard private static final WordComposer sEmptyWordComposer = new WordComposer(); 198441ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard public void updateBigramPredictions() { 198589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (mSuggest == null || !isSuggestionsRequested()) 198689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard return; 198789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 198817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (!mSettingsValues.mBigramPredictionEnabled) { 1989cb3320179d39a7983874697a0aa428b127675c9dJean Chalard setPunctuationSuggestions(); 1990cb3320179d39a7983874697a0aa428b127675c9dJean Chalard return; 1991cb3320179d39a7983874697a0aa428b127675c9dJean Chalard } 1992cb3320179d39a7983874697a0aa428b127675c9dJean Chalard 199389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(), 199417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mWordSeparators); 1995904baab25a4c6ec5d9c4bf7e562154e3f544d296satok SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(sEmptyWordComposer, 19963708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(), mCorrectionMode); 199789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 199889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (builder.size() > 0) { 199989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Explicitly supply an empty typed word (the no-second-arg version of 200089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // showSuggestions will retrieve the word near the cursor, we don't want that here) 200189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard showSuggestions(builder.build(), ""); 200289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 200389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (!isShowingPunctuationList()) setPunctuationSuggestions(); 200489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 200589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 200689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 20077a8dac55278cedd838be325f56b4c52d973c61f5satok public void setPunctuationSuggestions() { 200817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard setSuggestions(mSettingsValues.mSuggestPuncList); 2009913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShown(isSuggestionsStripVisible()); 20106a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 20116a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 2012f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard private void addToUserUnigramAndBigramDictionaries(CharSequence suggestion, 2013f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard int frequencyDelta) { 2014979f8690967ff5409fe18f5085858ccdb8e0ccf1satok checkAddToDictionary(suggestion, frequencyDelta, false); 2015979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2016979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2017bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok private void addToOnlyBigramDictionary(CharSequence suggestion, int frequencyDelta) { 2018979f8690967ff5409fe18f5085858ccdb8e0ccf1satok checkAddToDictionary(suggestion, frequencyDelta, true); 2019979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2020979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2021979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 2022f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard * Adds to the UserBigramDictionary and/or UserUnigramDictionary 2023bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok * @param selectedANotTypedWord true if it should be added to bigram dictionary if possible 2024979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 2025979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void checkAddToDictionary(CharSequence suggestion, int frequencyDelta, 2026bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok boolean selectedANotTypedWord) { 2027979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (suggestion == null || suggestion.length() < 1) return; 2028bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok 20290c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be 20300c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // adding words in situations where the user or application really didn't 20310c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // want corrections enabled or learned. 2032979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (!(mCorrectionMode == Suggest.CORRECTION_FULL 2033979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) { 2034979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return; 2035979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2036bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok 20375955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard if (null != mSuggest && null != mUserUnigramDictionary) { 20385955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard final boolean selectedATypedWordAndItsInUserUnigramDic = 20395955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard !selectedANotTypedWord && mUserUnigramDictionary.isValidWord(suggestion); 20405955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard final boolean isValidWord = AutoCorrection.isValidWord( 20415955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard mSuggest.getUnigramDictionaries(), suggestion, true); 20425955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard final boolean needsToAddToUserUnigramDictionary = 20435955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard selectedATypedWordAndItsInUserUnigramDic || !isValidWord; 20445955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard if (needsToAddToUserUnigramDictionary) { 20455955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard mUserUnigramDictionary.addWord(suggestion.toString(), frequencyDelta); 20465955cfdaeae9ce2120769a4be965bdbac413bf79Jean Chalard } 2047e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 2048979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2049e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mUserBigramDictionary != null) { 2050863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // We don't want to register as bigrams words separated by a separator. 2051863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // For example "I will, and you too" : we don't want the pair ("will" "and") to be 2052863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // a bigram. 205340f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final InputConnection ic = getCurrentInputConnection(); 205440f7efc172928bdd6048e91421a766abe5b22996Jean Chalard if (null != ic) { 205540f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final CharSequence prevWord = 205640f7efc172928bdd6048e91421a766abe5b22996Jean Chalard EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators); 205740f7efc172928bdd6048e91421a766abe5b22996Jean Chalard if (!TextUtils.isEmpty(prevWord)) { 205840f7efc172928bdd6048e91421a766abe5b22996Jean Chalard mUserBigramDictionary.addBigrams(prevWord.toString(), suggestion.toString()); 205940f7efc172928bdd6048e91421a766abe5b22996Jean Chalard } 2060979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 206132e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 206232e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 206332e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani 20647a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isCursorTouchingWord() { 20659351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 2066923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return false; 2067923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toLeft = ic.getTextBeforeCursor(1, 0); 2068923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toRight = ic.getTextAfterCursor(1, 0); 2069923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!TextUtils.isEmpty(toLeft) 207017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isWordSeparator(toLeft.charAt(0)) 207117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isSuggestedPunctuation(toLeft.charAt(0))) { 2072923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 2073923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2074a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker if (!TextUtils.isEmpty(toRight) 207517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isWordSeparator(toRight.charAt(0)) 207617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isSuggestedPunctuation(toRight.charAt(0))) { 2077923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 2078923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2079923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 2080923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2081a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2082120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // "ic" must not be null 20838fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka private static boolean sameAsTextBeforeCursor(final InputConnection ic, CharSequence text) { 2084dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0); 2085dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani return TextUtils.equals(text, beforeText); 2086dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani } 2087dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 2088120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // "ic" must not be null 20896b1f500da451de56932a8b2a99c63857994ece85Jean Chalard /** 20906b1f500da451de56932a8b2a99c63857994ece85Jean Chalard * Check if the cursor is actually at the end of a word. If so, restart suggestions on this 20916b1f500da451de56932a8b2a99c63857994ece85Jean Chalard * word, else do nothing. 20926b1f500da451de56932a8b2a99c63857994ece85Jean Chalard */ 20936b1f500da451de56932a8b2a99c63857994ece85Jean Chalard private void restartSuggestionsOnWordBeforeCursorIfAtEndOfWord( 20946b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final InputConnection ic) { 20956b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Bail out if the cursor is not at the end of a word (cursor must be preceded by 20966b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // non-whitespace, non-separator, non-start-of-text) 20976b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Example ("|" is the cursor here) : <SOL>"|a" " |a" " | " all get rejected here. 20986b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final CharSequence textBeforeCursor = ic.getTextBeforeCursor(1, 0); 20996b1f500da451de56932a8b2a99c63857994ece85Jean Chalard if (TextUtils.isEmpty(textBeforeCursor) 21006b1f500da451de56932a8b2a99c63857994ece85Jean Chalard || mSettingsValues.isWordSeparator(textBeforeCursor.charAt(0))) return; 21016b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 21026b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Bail out if the cursor is in the middle of a word (cursor must be followed by whitespace, 21036b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // separator or end of line/text) 21046b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Example: "test|"<EOL> "te|st" get rejected here 21056b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final CharSequence textAfterCursor = ic.getTextAfterCursor(1, 0); 21066b1f500da451de56932a8b2a99c63857994ece85Jean Chalard if (!TextUtils.isEmpty(textAfterCursor) 21076b1f500da451de56932a8b2a99c63857994ece85Jean Chalard && !mSettingsValues.isWordSeparator(textAfterCursor.charAt(0))) return; 21086b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 21096b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Bail out if word before cursor is 0-length or a single non letter (like an apostrophe) 2110fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // Example: " -|" gets rejected here but "e-|" and "e|" are okay 2111fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard CharSequence word = EditingUtils.getWordAtCursor(ic, mSettingsValues.mWordSeparators); 2112fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // We don't suggest on leading single quotes, so we have to remove them from the word if 2113fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // it starts with single quotes. 2114fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard while (!TextUtils.isEmpty(word) && Keyboard.CODE_SINGLE_QUOTE == word.charAt(0)) { 2115fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard word = word.subSequence(1, word.length()); 2116fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard } 21176b1f500da451de56932a8b2a99c63857994ece85Jean Chalard if (TextUtils.isEmpty(word)) return; 2118fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard final char firstChar = word.charAt(0); // we just tested that word is not empty 2119fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard if (word.length() == 1 && !Character.isLetter(firstChar)) return; 2120fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard 2121fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // We only suggest on words that start with a letter or a symbol that is excluded from 2122fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // word separators (see #handleCharacterWhileInBatchEdit). 2123fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard if (!(isAlphabet(firstChar) 2124fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard || mSettingsValues.isSymbolExcludedFromWordSeparators(firstChar))) { 2125fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard return; 2126fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard } 21276b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 21286b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Okay, we are at the end of a word. Restart suggestions. 21296b1f500da451de56932a8b2a99c63857994ece85Jean Chalard restartSuggestionsOnWordBeforeCursor(ic, word); 21306b1f500da451de56932a8b2a99c63857994ece85Jean Chalard } 21316b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 21326b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // "ic" must not be null 21336b1f500da451de56932a8b2a99c63857994ece85Jean Chalard private void restartSuggestionsOnWordBeforeCursor(final InputConnection ic, 21346b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final CharSequence word) { 21353708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka mWordComposer.setComposingWord(word, mKeyboardSwitcher.getKeyboard()); 21366b1f500da451de56932a8b2a99c63857994ece85Jean Chalard mComposingStateManager.onStartComposingText(); 21376b1f500da451de56932a8b2a99c63857994ece85Jean Chalard ic.deleteSurroundingText(word.length(), 0); 21386b1f500da451de56932a8b2a99c63857994ece85Jean Chalard ic.setComposingText(word, 1); 21396b1f500da451de56932a8b2a99c63857994ece85Jean Chalard mHandler.postUpdateSuggestions(); 21406b1f500da451de56932a8b2a99c63857994ece85Jean Chalard } 21416b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 21426b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // "ic" must not be null 2143890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard private void cancelAutoCorrect(final InputConnection ic) { 21449e8761c4402ddc11c942ed2e583bd7d58f70c5eaJean Chalard mWordComposer.resumeSuggestionOnKeptWord(); 21459e8761c4402ddc11c942ed2e583bd7d58f70c5eaJean Chalard final String originallyTypedWord = mWordComposer.getTypedWord(); 21469e8761c4402ddc11c942ed2e583bd7d58f70c5eaJean Chalard final CharSequence autoCorrectedTo = mWordComposer.getAutoCorrectionOrNull(); 21479e8761c4402ddc11c942ed2e583bd7d58f70c5eaJean Chalard final int cancelLength = autoCorrectedTo.length(); 2148890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard final CharSequence separator = ic.getTextBeforeCursor(1, 0); 2149890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard if (DEBUG) { 2150890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard final String wordBeforeCursor = 2151890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard ic.getTextBeforeCursor(cancelLength + 1, 0).subSequence(0, cancelLength) 2152890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard .toString(); 21537546ff6e34d540e9529d785bfc691b9c155b4051Jean Chalard if (!TextUtils.equals(autoCorrectedTo, wordBeforeCursor)) { 2154890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard throw new RuntimeException("cancelAutoCorrect check failed: we thought we were " 21559e8761c4402ddc11c942ed2e583bd7d58f70c5eaJean Chalard + "reverting \"" + autoCorrectedTo 2156890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard + "\", but before the cursor we found \"" + wordBeforeCursor + "\""); 2157890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard } 21587546ff6e34d540e9529d785bfc691b9c155b4051Jean Chalard if (TextUtils.equals(originallyTypedWord, wordBeforeCursor)) { 2159890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard throw new RuntimeException("cancelAutoCorrect check failed: we wanted to cancel " 21609e8761c4402ddc11c942ed2e583bd7d58f70c5eaJean Chalard + "auto correction and revert to \"" + originallyTypedWord 2161890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard + "\" but we found this very string before the cursor"); 2162890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard } 21638558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa } 2164890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard ic.deleteSurroundingText(cancelLength + 1, 0); 21659e8761c4402ddc11c942ed2e583bd7d58f70c5eaJean Chalard ic.commitText(originallyTypedWord, 1); 2166c73c26790fa9dcd836a918774d6efa39a05c0152Jean Chalard // Re-insert the separator 2167890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard ic.commitText(separator, 1); 21689e8761c4402ddc11c942ed2e583bd7d58f70c5eaJean Chalard mWordComposer.deleteAutoCorrection(); 21690fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard mWordComposer.onCommitWord(WordComposer.COMMIT_TYPE_CANCEL_AUTO_CORRECT); 2170406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard Utils.Stats.onSeparator(separator.charAt(0), WordComposer.NOT_A_COORDINATE, 2171406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard WordComposer.NOT_A_COORDINATE); 2172890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard mHandler.cancelUpdateBigramPredictions(); 2173890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard mHandler.postUpdateSuggestions(); 2174890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard } 2175890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard 2176890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard // "ic" must not be null 2177890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard private void restartSuggestionsOnManuallyPickedTypedWord(final InputConnection ic) { 21783b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // Note: this relies on the last word still being held in the WordComposer, in 21793b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // the field for suggestion resuming. 21803b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // Note: in the interest of code simplicity, we may want to just call 21813b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // restartSuggestionsOnWordBeforeCursorIfAtEndOfWord instead, but retrieving 21823b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // the old WordComposer allows to reuse the actual typed coordinates. 21833b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard mWordComposer.resumeSuggestionOnKeptWord(); 21843b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // We resume suggestion, and then we want to set the composing text to the content 21853b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // of the word composer again. But since we just manually picked a word, there is 21863b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // no composing text at the moment, so we have to delete the word before we set a 21873b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // new composing text. 2188c2a76a1529870b59bba133a7d76a800cbd20ecfaJean Chalard final int restartLength = mWordComposer.size(); 2189890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard if (DEBUG) { 2190890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard final String wordBeforeCursor = 2191890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard ic.getTextBeforeCursor(restartLength + 1, 0).subSequence(0, restartLength) 2192890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard .toString(); 21937546ff6e34d540e9529d785bfc691b9c155b4051Jean Chalard if (!TextUtils.equals(mWordComposer.getTypedWord(), wordBeforeCursor)) { 2194890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard throw new RuntimeException("restartSuggestionsOnManuallyPickedTypedWord " 2195890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard + "check failed: we thought we were reverting \"" 2196890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard + mWordComposer.getTypedWord() 2197890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard + "\", but before the cursor we found \"" 2198890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard + wordBeforeCursor + "\""); 2199890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard } 2200923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 22013b2112e70aa7474dbd0a879bfba5f7b1ce0a89adJean Chalard // Warning: this +1 takes into account the extra space added by the manual pick process. 2202890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard ic.deleteSurroundingText(restartLength + 1, 0); 2203890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard ic.setComposingText(mWordComposer.getTypedWord(), 1); 22048558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa mHandler.cancelUpdateBigramPredictions(); 22058558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa mHandler.postUpdateSuggestions(); 2206923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2207923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2208120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // "ic" must not be null 22099351550dc6af7859e5280e16144c9386a37b976dKen Wakasa private boolean revertDoubleSpace(final InputConnection ic) { 22104733609947c0ec74e460bd714fffca0518ade93aJean Chalard mHandler.cancelDoubleSpacesTimer(); 22114733609947c0ec74e460bd714fffca0518ade93aJean Chalard // Here we test whether we indeed have a period and a space before us. This should not 22124733609947c0ec74e460bd714fffca0518ade93aJean Chalard // be needed, but it's there just in case something went wrong. 22134733609947c0ec74e460bd714fffca0518ade93aJean Chalard final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0); 22148ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard if (!". ".equals(textBeforeCursor)) { 22158ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard // We should not have come here if we aren't just after a ". ". 22168ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard throw new RuntimeException("Tried to revert double-space combo but we didn't find " 22178ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard + "\". \" just before the cursor."); 22188ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard } 22194733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.beginBatchEdit(); 22204733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.deleteSurroundingText(2, 0); 22214733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.commitText(" ", 1); 22224733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.endBatchEdit(); 22234733609947c0ec74e460bd714fffca0518ade93aJean Chalard return true; 22244733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 22254733609947c0ec74e460bd714fffca0518ade93aJean Chalard 22268fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka private static boolean revertSwapPunctuation(final InputConnection ic) { 2227120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Here we test whether we indeed have a space and something else before us. This should not 2228120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // be needed, but it's there just in case something went wrong. 2229120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0); 2230120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // NOTE: This does not work with surrogate pairs. Hopefully when the keyboard is able to 2231120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // enter surrogate pairs this code will have been removed. 22328be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard if (TextUtils.isEmpty(textBeforeCursor) 22338be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard || (Keyboard.CODE_SPACE != textBeforeCursor.charAt(1))) { 22348be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard // We may only come here if the application is changing the text while we are typing. 22358be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard // This is quite a broken case, but not logically impossible, so we shouldn't crash, 22368be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard // but some debugging log may be in order. 22378be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard Log.d(TAG, "Tried to revert a swap of punctuation but we didn't " 22388ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard + "find a space just before the cursor."); 22398be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard return false; 22408ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard } 2241120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.beginBatchEdit(); 2242120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.deleteSurroundingText(2, 0); 2243120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.commitText(" " + textBeforeCursor.subSequence(0, 1), 1); 2244120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.endBatchEdit(); 2245120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return true; 2246120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 2247120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 2248923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean isWordSeparator(int code) { 224917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard return mSettingsValues.isWordSeparator(code); 2250923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2251923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 22520730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard private void sendMagicSpace() { 2253571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka sendKeyChar((char)Keyboard.CODE_SPACE); 2254120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_MAGIC; 2255b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 2256923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2257923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2258923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean preferCapitalization() { 22599318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa return mWordComposer.isFirstCharCapitalized(); 2260923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2261923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 226288fc9d44186120f9edc5cf7ec0e2af85260fed04satok // Notify that language or mode have been changed and toggleLanguage will update KeyboardID 2263c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // according to new language or mode. 2264c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka public void onRefreshKeyboard() { 226555303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) { 226655303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka // Before Honeycomb, Voice IME is in LatinIME and it changes the current input view, 226755303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka // so that we need to re-create the keyboard input view here. 226855303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka setInputView(mKeyboardSwitcher.onCreateInputView()); 226955303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka } 22701e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka // When the device locale is changed in SetupWizard etc., this method may get called via 22711e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka // onConfigurationChanged before SoftInputWindow is shown. 22721e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka if (mKeyboardSwitcher.getKeyboardView() != null) { 22731e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka // Reload keyboard because the current language has been changed. 22741e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettingsValues); 22751e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka } 22760ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 227717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 227836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 227936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 2280d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka private void hapticAndAudioFeedback(int primaryCode) { 2281d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka vibrate(); 2282d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka playKeyClick(primaryCode); 2283d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka } 2284d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka 22855a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 22862a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka public void onPressKey(int primaryCode) { 2287055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 2288055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka if (switcher.isVibrateAndSoundFeedbackRequired()) { 2289d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka hapticAndAudioFeedback(primaryCode); 2290cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka } 22912a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka switcher.onPressKey(primaryCode); 2292923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2293923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 22945a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 22952a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka public void onReleaseKey(int primaryCode, boolean withSliding) { 22962a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka mKeyboardSwitcher.onReleaseKey(primaryCode, withSliding); 2297923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2298a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2299a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2300123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka // receive ringer mode change and network state change. 2301923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private BroadcastReceiver mReceiver = new BroadcastReceiver() { 2302923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 2303923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onReceive(Context context, Intent intent) { 2304123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final String action = intent.getAction(); 2305123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { 2306123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka updateRingerMode(); 2307123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 2308123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka mSubtypeSwitcher.onNetworkStateChanged(intent); 2309123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } 2310923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2311923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project }; 2312923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2313923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // update flags for silent mode 2314923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void updateRingerMode() { 2315923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 2316923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 2317bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa if (mAudioManager == null) return; 2318923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2319bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa mSilentModeOn = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL); 2320923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2321923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2322923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void playKeyClick(int primaryCode) { 2323923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // if mAudioManager is null, we don't have the ringer state yet 2324923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // mAudioManager will be set by updateRingerMode 2325923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 2326c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka if (mKeyboardSwitcher.getKeyboardView() != null) { 2327923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateRingerMode(); 2328923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2329923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 233017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (isSoundOn()) { 2331f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa final int sound; 2332923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 2333f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa case Keyboard.CODE_DELETE: 2334f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa sound = AudioManager.FX_KEYPRESS_DELETE; 2335f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa break; 2336f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa case Keyboard.CODE_ENTER: 2337f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa sound = AudioManager.FX_KEYPRESS_RETURN; 2338f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa break; 2339f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa case Keyboard.CODE_SPACE: 2340f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa sound = AudioManager.FX_KEYPRESS_SPACEBAR; 2341f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa break; 2342f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa default: 2343f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa sound = AudioManager.FX_KEYPRESS_STANDARD; 2344f58293f6ebf821acd9a3cc594124e905c4592810Ken Wakasa break; 2345923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2346c207e0a7dad0bdae054be47cafe878698f9401fcJean Chalard mAudioManager.playSoundEffect(sound, mSettingsValues.mFxVolume); 2347923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2348923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2349923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2350409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void vibrate() { 235117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (!mSettingsValues.mVibrateOn) { 2352923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 2353923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2354c207e0a7dad0bdae054be47cafe878698f9401fcJean Chalard if (mSettingsValues.mKeypressVibrationDuration < 0) { 235528f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa // Go ahead with the system default 235628f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 235728f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa if (inputView != null) { 235828f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa inputView.performHapticFeedback( 235928f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa HapticFeedbackConstants.KEYBOARD_TAP, 236028f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); 236128f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa } 236228f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa } else if (mVibrator != null) { 2363c207e0a7dad0bdae054be47cafe878698f9401fcJean Chalard mVibrator.vibrate(mSettingsValues.mKeypressVibrationDuration); 2364923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2365923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2366923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2367f7d6517d6b1a1dd88e2142e1a15703bb839be01bJean Chalard public boolean isAutoCapitalized() { 2368f7d6517d6b1a1dd88e2142e1a15703bb839be01bJean Chalard return mWordComposer.isAutoCapitalized(); 23696516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani } 23706516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani 237117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard boolean isSoundOn() { 237217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard return mSettingsValues.mSoundOn && !mSilentModeOn; 2373979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2374979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2375e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private void updateCorrectionMode() { 23769f67e12a0e3f77985fb8bafe0db4c00e32317b9asatok // TODO: cleanup messy flags 2377f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled 2378dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard && !mInputAttributes.mInputTypeNoAutoCorrect; 2379283b0c2b642030539ba3e41f3f54b6aed6bb9e2dJean Chalard mCorrectionMode = shouldAutoCorrect ? Suggest.CORRECTION_FULL : Suggest.CORRECTION_NONE; 2380283b0c2b642030539ba3e41f3f54b6aed6bb9e2dJean Chalard mCorrectionMode = (mSettingsValues.mBigramSuggestionEnabled && shouldAutoCorrect) 2381979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ? Suggest.CORRECTION_FULL_BIGRAM : mCorrectionMode; 2382e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 2383e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani 23842ac5988f84b5c38d313951a3d7faddebf5f25e04Tadashi G. Takaoka private void updateSuggestionVisibility(final Resources res) { 23850fe3611bee5095e7bd0fff2d0fdf8d5a13379132Jean Chalard final String suggestionVisiblityStr = mSettingsValues.mShowSuggestionsSetting; 23867599cfea4a2d56f4779452ec8e8742f7b9629cc0satok for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) { 2387458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa if (suggestionVisiblityStr.equals(res.getString(visibility))) { 23887599cfea4a2d56f4779452ec8e8742f7b9629cc0satok mSuggestionVisibility = visibility; 23897599cfea4a2d56f4779452ec8e8742f7b9629cc0satok break; 23907599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 23917599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 23927599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 23937599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 2394466741d8a78965b8509bf527344f289e50873092Mike LeBeau protected void launchSettings() { 2395cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa launchSettingsClass(Settings.class); 2396466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 2397466741d8a78965b8509bf527344f289e50873092Mike LeBeau 2398bf96661d33d0126adb60a48880ceba1ff055d4a4satok public void launchDebugSettings() { 2399cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa launchSettingsClass(DebugSettings.class); 2400bf96661d33d0126adb60a48880ceba1ff055d4a4satok } 2401bf96661d33d0126adb60a48880ceba1ff055d4a4satok 2402cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa protected void launchSettingsClass(Class<? extends PreferenceActivity> settingsClass) { 2403923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project handleClose(); 2404923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Intent intent = new Intent(); 2405466741d8a78965b8509bf527344f289e50873092Mike LeBeau intent.setClass(LatinIME.this, settingsClass); 2406923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2407923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project startActivity(intent); 2408923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2409923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 24102fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showSubtypeSelectorAndSettings() { 241185996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 241285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 241385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka // TODO: Should use new string "Select active input modes". 241485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.language_selection_title), 241585996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 241685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 241785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 24182fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka @Override 24192fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka public void onClick(DialogInterface di, int position) { 24202fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka di.dismiss(); 24212fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka switch (position) { 242285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 24232cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok Intent intent = CompatUtils.getInputLanguageSelectionIntent( 24242a659b8aa642b0832fa0ac9a93e0640592fcc239Jean Chalard Utils.getInputMethodId(mImm, getPackageName()), 24252a659b8aa642b0832fa0ac9a93e0640592fcc239Jean Chalard Intent.FLAG_ACTIVITY_NEW_TASK 24262fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 24272fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_CLEAR_TOP); 24282fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka startActivity(intent); 24292fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2430aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa case 1: 2431aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa launchSettings(); 2432aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa break; 24332fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 24342fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 243585996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 2436bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka final AlertDialog.Builder builder = new AlertDialog.Builder(this) 2437bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setItems(items, listener) 2438bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setTitle(title); 2439bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka showOptionDialogInternal(builder.create()); 24402fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 2441923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 24422fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showOptionsMenu() { 244385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 244485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 244585996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.selectInputMethod), 244685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 244785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 244885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 24495a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 2450923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onClick(DialogInterface di, int position) { 2451923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project di.dismiss(); 2452923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (position) { 245385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 2454ea55bf5df7d26d12b36c47141bfbac5730c3929aTadashi G. Takaoka mImm.showInputMethodPicker(); 24552fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 245685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 1: 2457ea55bf5df7d26d12b36c47141bfbac5730c3929aTadashi G. Takaoka launchSettings(); 24582fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2459923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2460923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 246185996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 2462bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka final AlertDialog.Builder builder = new AlertDialog.Builder(this) 2463bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setItems(items, listener) 2464bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setTitle(title); 2465bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka showOptionDialogInternal(builder.create()); 2466923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2467923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 24687e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 24697e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 2470923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.dump(fd, fout, args); 2471a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2472923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final Printer p = new PrintWriterPrinter(fout); 2473923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println("LatinIME state :"); 24743708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); 2475df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka final int keyboardMode = keyboard != null ? keyboard.mId.mMode : -1; 2476df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka p.println(" Keyboard mode = " + keyboardMode); 2477dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard p.println(" mIsSuggestionsRequested=" + mInputAttributes.mIsSettingsSuggestionStripOn); 2478923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mCorrectionMode=" + mCorrectionMode); 24794d0f03bd66742ee292da81a3e025e119f28b6940Jean Chalard p.println(" isComposingWord=" + mWordComposer.isComposingWord()); 248017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mAutoCorrectEnabled=" + mSettingsValues.mAutoCorrectEnabled); 248117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mSoundOn=" + mSettingsValues.mSoundOn); 248217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mVibrateOn=" + mSettingsValues.mVibrateOn); 2483240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard p.println(" mKeyPreviewPopupOn=" + mSettingsValues.mKeyPreviewPopupOn); 24846fa003ee234c6e2ca6cd9ec555221ac5c71a5405Jean Chalard p.println(" mInputAttributes=" + mInputAttributes.toString()); 2485923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2486923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 2487