LatinIME.java revision 660776e09b9a3b321074a94721d901a035ca1b9f
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; 28c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaokaimport android.graphics.Rect; 29923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.inputmethodservice.InputMethodService; 30923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.media.AudioManager; 31123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaokaimport android.net.ConnectivityManager; 32923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Debug; 3381d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaokaimport android.os.IBinder; 34923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Message; 35923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.SystemClock; 36bf96661d33d0126adb60a48880ceba1ff055d4a4satokimport android.preference.PreferenceActivity; 37923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.preference.PreferenceManager; 38e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaokaimport android.text.InputType; 39923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.text.TextUtils; 40923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Log; 41923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.PrintWriterPrinter; 42923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Printer; 43923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.KeyEvent; 44923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.View; 458e09172df1bb176cc899940862c56bed9b9aec4esatokimport android.view.ViewGroup; 46c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaokaimport android.view.ViewGroup.LayoutParams; 47cc8c8b99bd0463f5977dea82f5e2379ea1dd4e73Tadashi G. Takaokaimport android.view.ViewParent; 48923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.CompletionInfo; 49923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.EditorInfo; 50466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport android.view.inputmethod.ExtractedText; 51923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.InputConnection; 52c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka 535ac4638f999db4fea8a9e24171dbceb640a10858Alan Viveretteimport com.android.inputmethod.accessibility.AccessibilityUtils; 548d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanvimport com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; 55c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.CompatUtils; 56c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.EditorInfoCompatUtils; 57c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputConnectionCompatUtils; 58c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputMethodManagerCompatWrapper; 59c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputMethodServiceCompatWrapper; 6081d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaokaimport com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper; 61c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputTypeCompatUtils; 621fef530ec7626fa16777f52b48191e61db8f46d4satokimport com.android.inputmethod.compat.SuggestionSpanUtils; 63c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.deprecated.LanguageSwitcherProxy; 64c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.deprecated.VoiceProxy; 65c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.Keyboard; 66c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardActionListener; 676b7100fecaaaf0e8e42c4d2ccebac165e89e79bfTadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardId; 68c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardSwitcher; 69f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardView; 70c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaokaimport com.android.inputmethod.keyboard.LatinKeyboardView; 718c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaokaimport com.android.inputmethod.latin.suggestions.SuggestionsView; 72923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 73466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.FileDescriptor; 74466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.PrintWriter; 754ee186920e642ae8ebe0b6c97dfdceb0ad2fdeefJean Chalardimport java.util.ArrayList; 76466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.Locale; 77466741d8a78965b8509bf527344f289e50873092Mike LeBeau 78923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/** 79923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Input method implementation for Qwerty'ish keyboard. 80923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 81c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaokapublic class LatinIME extends InputMethodServiceCompatWrapper implements KeyboardActionListener, 82913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka SuggestionsView.Listener { 838efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka private static final String TAG = LatinIME.class.getSimpleName(); 84409220583333bdf06290dd9fd42f91b5c0d1b11asatok private static final boolean TRACE = false; 859e2d810dc524380ca1db6b384cfb00b4401585e5Tadashi G. Takaoka private static boolean DEBUG; 86a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 878efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka /** 888efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * The private IME option used to indicate that no microphone should be 898efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * shown for a given text field. For instance, this is specified by the 908efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * search dialog when the dialog is already showing a voice search button. 918efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * 928efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * @deprecated Use {@link LatinIME#IME_OPTION_NO_MICROPHONE} with package name prefixed. 938efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka */ 9410dd34de0ffcde0104f7d2dae3a3c9fd66abffccsatok @SuppressWarnings("dep-ann") 958efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka public static final String IME_OPTION_NO_MICROPHONE_COMPAT = "nm"; 968efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka 978efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka /** 988efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * The private IME option used to indicate that no microphone should be 998efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * shown for a given text field. For instance, this is specified by the 1008efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * search dialog when the dialog is already showing a voice search button. 1018efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka */ 1024199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka public static final String IME_OPTION_NO_MICROPHONE = "noMicrophoneKey"; 1034199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka 1044199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka /** 1054199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka * The private IME option used to indicate that no settings key should be 1064199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka * shown for a given text field. 1074199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka */ 1084199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka public static final String IME_OPTION_NO_SETTINGS_KEY = "noSettingsKey"; 1098efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka 110af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka /** 111af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka * The private IME option used to indicate that the given text field needs 112af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka * ASCII code points input. 1131ef6fc7e1519cedec9e84a64968bfba4212d0436Tadashi G. Takaoka * 1141ef6fc7e1519cedec9e84a64968bfba4212d0436Tadashi G. Takaoka * @deprecated Use {@link EditorInfo#IME_FLAG_FORCE_ASCII}. 115af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka */ 1161ef6fc7e1519cedec9e84a64968bfba4212d0436Tadashi G. Takaoka @SuppressWarnings("dep-ann") 117af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka public static final String IME_OPTION_FORCE_ASCII = "forceAscii"; 118af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka 119af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka /** 120af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka * The subtype extra value used to indicate that the subtype keyboard layout is capable for 121af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka * typing ASCII characters. 122af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka */ 123af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka public static final String SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable"; 124af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka 125d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka /** 126294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima * The subtype extra value used to indicate that the subtype keyboard layout supports touch 127294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima * position correction. 128294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima */ 129294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima public static final String SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION = 130294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima "SupportTouchPositionCorrection"; 131294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima /** 132d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka * The subtype extra value used to indicate that the subtype keyboard layout should be loaded 133d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka * from the specified locale. 134d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka */ 135d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka public static final String SUBTYPE_EXTRA_VALUE_KEYBOARD_LOCALE = "KeyboardLocale"; 136d81479a340d76afaef14ce683322e1488167919cTadashi G. Takaoka 1379e347d3d448e48229c46aad394ec9bd60cd5807bsatok private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100; 138fd0bd57deb53c4cce32810a61133fa44b45dbb7bKen Wakasa 139923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // How many continuous deletes at which to start deleting at a higher speed. 140923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int DELETE_ACCELERATE_AT = 20; 141923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Key events coming any faster than this are long-presses. 142d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani private static final int QUICK_PRESS = 200; 143a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 14459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private static final int PENDING_IMS_CALLBACK_DURATION = 800; 145055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 146cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard /** 147cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard * The name of the scheme used by the Package Manager to warn of a new package installation, 148cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard * replacement or removal. 149cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard */ 150cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard private static final String SCHEME_PACKAGE = "package"; 151cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 1520fe3611bee5095e7bd0fff2d0fdf8d5a13379132Jean Chalard // TODO: migrate this to SettingsValues 1537599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private int mSuggestionVisibility; 1547599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_VALUE 1557599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_value; 1567599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 1577599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_only_portrait_value; 1587599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_HIDE_VALUE 1597599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_hide_value; 1607599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 1617599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int[] SUGGESTION_VISIBILITY_VALUE_ARRAY = new int[] { 1627599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_VALUE, 1637599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE, 1647599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_HIDE_VALUE 1657599cfea4a2d56f4779452ec8e8742f7b9629cc0satok }; 1667599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 167fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard private static final int SPACE_STATE_NONE = 0; 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. 170fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard private static final int SPACE_STATE_DOUBLE = 1; 171b141c9cd3f6785bc0a4e1f5385f4e6e2e17955bbJean Chalard // Swap punctuation: the state where a weak space and a punctuation from the suggestion strip 172b141c9cd3f6785bc0a4e1f5385f4e6e2e17955bbJean Chalard // have just been swapped. Undoing this swaps them back; the space is still considered weak. 173120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private static final int SPACE_STATE_SWAP_PUNCTUATION = 2; 174fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // Weak space: a space that should be swapped only by suggestion strip punctuation. Weak 175fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // spaces happen when the user presses space, accepting the current suggestion (whether 176fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // it's an auto-correction or not). 177fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard private static final int SPACE_STATE_WEAK = 3; 178fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // Phantom space: a not-yet-inserted space that should get inserted on the next input, 179fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // character provided it's not a separator. If it's a separator, the phantom space is dropped. 180fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // Phantom spaces happen when a user chooses a word from the suggestion strip. 181fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard private static final int SPACE_STATE_PHANTOM = 4; 182120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 183120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Current space state of the input method. This can be any of the above constants. 184120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private int mSpaceState; 185126698fdd256a2e3734634d3b923cabd800064baJean Chalard 1867a16a061e622539e54d7d649dcb8d4965aea575aJean Chalard private SettingsValues mSettingsValues; 18780b66bb166f7f45adfcadcb84788477df9930828Jean Chalard private InputAttributes mInputAttributes; 18817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 189d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka private View mExtractArea; 190abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka private View mKeyPreviewBackingView; 191913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka private View mSuggestionsContainer; 192913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka private SuggestionsView mSuggestionsView; 193816a8a0fd85ca0327436f8bd1cfa6928600ebc5dJean Chalard /* package for tests */ Suggest mSuggest; 1941b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka private CompletionInfo[] mApplicationSpecifiedCompletions; 195a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 196610f1dc8553cf2ed97e763a06a19380c4a6cd636satok private InputMethodManagerCompatWrapper mImm; 1972fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private Resources mResources; 1982fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private SharedPreferences mPrefs; 19989ffb212b469531db4a616afb9bb7ba6d2a56b50Jean Chalard private final KeyboardSwitcher mKeyboardSwitcher; 20089ffb212b469531db4a616afb9bb7ba6d2a56b50Jean Chalard private final SubtypeSwitcher mSubtypeSwitcher; 201b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok private VoiceProxy mVoiceProxy; 20281d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka private boolean mShouldSwitchToLastSubtype = true; 203a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 204923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private UserDictionary mUserDictionary; 205979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private UserBigramDictionary mUserBigramDictionary; 20688562bec54658840dcce352127bdc15705c20a89Jean Chalard private boolean mIsUserDictionaryAvailable; 20736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 2082692a8700737d8eed268039aa27b22a31669da08Jean Chalard private LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; 2099318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa private WordComposer mWordComposer = new WordComposer(); 210409220583333bdf06290dd9fd42f91b5c0d1b11asatok 21179efbed76f638be298493107fa2d0cd1b5eb529esatok private int mCorrectionMode; 21277da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard 213979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Keep track of the last selection range to decide if we need to show word alternatives 21477da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard private static final int NOT_A_CURSOR_POSITION = -1; 21577da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard private int mLastSelectionStart = NOT_A_CURSOR_POSITION; 21677da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard private int mLastSelectionEnd = NOT_A_CURSOR_POSITION; 217979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2184733609947c0ec74e460bd714fffca0518ade93aJean Chalard // Whether we are expecting an onUpdateSelection event to fire. If it does when we don't 2194733609947c0ec74e460bd714fffca0518ade93aJean Chalard // "expect" it, it means the user actually moved the cursor. 2204733609947c0ec74e460bd714fffca0518ade93aJean Chalard private boolean mExpectingUpdateSelection; 221923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mDeleteCount; 222923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastKeyTime; 223a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 224564496bad6207f02e7a653872213bc5954e84ce4Jean Chalard private AudioAndHapticFeedbackManager mFeedbackManager; 22528f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa 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 23670852c91dc7209d0aaa875a2cb0f79739c7398e6Jean Chalard private boolean mIsAutoCorrectionIndicatorOn; 237604d80c67185954d4691ac775be59c499eee3b1csatok 2384f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public final UIHandler mHandler = new UIHandler(this); 239d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 2404f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public static class UIHandler extends StaticInnerHandlerWrapper<LatinIME> { 24145f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_UPDATE_SHIFT_STATE = 1; 24245f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_VOICE_RESULTS = 2; 2434c0c638a189c1073b1fb6e43fe5fddb6f9932038Tadashi G. Takaoka private static final int MSG_SPACE_TYPED = 4; 2444c0c638a189c1073b1fb6e43fe5fddb6f9932038Tadashi G. Takaoka private static final int MSG_SET_BIGRAM_PREDICTIONS = 5; 2454c0c638a189c1073b1fb6e43fe5fddb6f9932038Tadashi G. Takaoka private static final int MSG_PENDING_IMS_CALLBACK = 6; 2464c0c638a189c1073b1fb6e43fe5fddb6f9932038Tadashi G. Takaoka private static final int MSG_UPDATE_SUGGESTIONS = 7; 2474c0c638a189c1073b1fb6e43fe5fddb6f9932038Tadashi G. Takaoka 24810dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private int mDelayUpdateSuggestions; 24910dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private int mDelayUpdateShiftState; 25010dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private long mDoubleSpacesTurnIntoPeriodTimeout; 25138f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 2524f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public UIHandler(LatinIME outerInstance) { 2534f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa super(outerInstance); 25410dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka } 255175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka 25610dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka public void onCreate() { 25710dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka final Resources res = getOuterInstance().getResources(); 258175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDelayUpdateSuggestions = 259175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka res.getInteger(R.integer.config_delay_update_suggestions); 260175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDelayUpdateShiftState = 261175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka res.getInteger(R.integer.config_delay_update_shift_state); 262175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDoubleSpacesTurnIntoPeriodTimeout = res.getInteger( 263175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka R.integer.config_double_spaces_turn_into_period_timeout); 2644f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa } 2654f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa 266923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 267923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void handleMessage(Message msg) { 2684f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final LatinIME latinIme = getOuterInstance(); 2694f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final KeyboardSwitcher switcher = latinIme.mKeyboardSwitcher; 270923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (msg.what) { 271d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SUGGESTIONS: 2724f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.updateSuggestions(); 273d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 274d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SHIFT_STATE: 275de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka switcher.updateShiftState(); 276d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 277cb3320179d39a7983874697a0aa428b127675c9dJean Chalard case MSG_SET_BIGRAM_PREDICTIONS: 2784f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.updateBigramPredictions(); 27989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard break; 280d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_VOICE_RESULTS: 281433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka final Keyboard keyboard = switcher.getKeyboard(); 2824f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mVoiceProxy.handleVoiceResults(latinIme.preferCapitalization() 283433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka || (keyboard != null && keyboard.isShiftedOrShiftLocked())); 284de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka break; 285923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 286923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 287d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 288d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateSuggestions() { 289d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 290175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS), mDelayUpdateSuggestions); 291d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 292d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 293d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateSuggestions() { 294d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 295d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 296d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 297d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public boolean hasPendingUpdateSuggestions() { 298d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka return hasMessages(MSG_UPDATE_SUGGESTIONS); 299d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 300d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 301beb08b398fa73a26f2d42d6feec87e34a96ca2d9Tadashi G. Takaoka public void postUpdateShiftState() { 302d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 303175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE), mDelayUpdateShiftState); 304d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 305d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 306d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateShiftState() { 307d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 308d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 309d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 310cb3320179d39a7983874697a0aa428b127675c9dJean Chalard public void postUpdateBigramPredictions() { 311cb3320179d39a7983874697a0aa428b127675c9dJean Chalard removeMessages(MSG_SET_BIGRAM_PREDICTIONS); 312175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS), mDelayUpdateSuggestions); 31389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 31489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 315cb3320179d39a7983874697a0aa428b127675c9dJean Chalard public void cancelUpdateBigramPredictions() { 316cb3320179d39a7983874697a0aa428b127675c9dJean Chalard removeMessages(MSG_SET_BIGRAM_PREDICTIONS); 31789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 31889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 319d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void updateVoiceResults() { 320d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessage(obtainMessage(MSG_VOICE_RESULTS)); 321d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 322de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka 323fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public void startDoubleSpacesTimer() { 324fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka removeMessages(MSG_SPACE_TYPED); 325175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED), mDoubleSpacesTurnIntoPeriodTimeout); 326fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 327fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 328fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public void cancelDoubleSpacesTimer() { 329fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka removeMessages(MSG_SPACE_TYPED); 330fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 331fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 332fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public boolean isAcceptingDoubleSpaces() { 333fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka return hasMessages(MSG_SPACE_TYPED); 334fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 33538f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 33659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Working variables for the following methods. 33759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mIsOrientationChanging; 3385fd11a7f3367d51cea8dc83fb9675c93d82a2e4eJean Chalard private boolean mPendingSuccessiveImsCallback; 33959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mHasPendingStartInput; 34059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mHasPendingFinishInputView; 34159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mHasPendingFinishInput; 342e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka private EditorInfo mAppliedEditorInfo; 34359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 34459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void startOrientationChanging() { 345dd25e4fa2c7dd1e32a9e6f5fd21f54214919ef20Tadashi G. Takaoka removeMessages(MSG_PENDING_IMS_CALLBACK); 346dd25e4fa2c7dd1e32a9e6f5fd21f54214919ef20Tadashi G. Takaoka resetPendingImsCallback(); 34759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mIsOrientationChanging = true; 348055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 349f2c9a88887a303f3df8bee60788870946dfa55f7Tadashi G. Takaoka if (latinIme.isInputViewShown()) { 350f2c9a88887a303f3df8bee60788870946dfa55f7Tadashi G. Takaoka latinIme.mKeyboardSwitcher.saveKeyboardState(); 351f2c9a88887a303f3df8bee60788870946dfa55f7Tadashi G. Takaoka } 35259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 35359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 35459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void resetPendingImsCallback() { 35559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInputView = false; 35659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInput = false; 35759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingStartInput = false; 35859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 35959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 360e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka private void executePendingImsCallback(LatinIME latinIme, EditorInfo editorInfo, 36159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka boolean restarting) { 36259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mHasPendingFinishInputView) 36359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputViewInternal(mHasPendingFinishInput); 36459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mHasPendingFinishInput) 36559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputInternal(); 36659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mHasPendingStartInput) 367e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka latinIme.onStartInputInternal(editorInfo, restarting); 36859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka resetPendingImsCallback(); 36959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 37059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 371e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka public void onStartInput(EditorInfo editorInfo, boolean restarting) { 37259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { 37359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Typically this is the second onStartInput after orientation changed. 37459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingStartInput = true; 37559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } else { 37659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mIsOrientationChanging && restarting) { 37759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // This is the first onStartInput after orientation changed. 37859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mIsOrientationChanging = false; 3795fd11a7f3367d51cea8dc83fb9675c93d82a2e4eJean Chalard mPendingSuccessiveImsCallback = true; 38059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 38159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 382e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka executePendingImsCallback(latinIme, editorInfo, restarting); 383e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka latinIme.onStartInputInternal(editorInfo, restarting); 384055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 385055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 386055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 387e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka public void onStartInputView(EditorInfo editorInfo, boolean restarting) { 3886b7100fecaaaf0e8e42c4d2ccebac165e89e79bfTadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK) 3896b7100fecaaaf0e8e42c4d2ccebac165e89e79bfTadashi G. Takaoka && KeyboardId.equivalentEditorInfoForKeyboard(editorInfo, mAppliedEditorInfo)) { 390e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka // Typically this is the second onStartInputView after orientation changed. 391e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka resetPendingImsCallback(); 392e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka } else { 3935fd11a7f3367d51cea8dc83fb9675c93d82a2e4eJean Chalard if (mPendingSuccessiveImsCallback) { 394e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka // This is the first onStartInputView after orientation changed. 3955fd11a7f3367d51cea8dc83fb9675c93d82a2e4eJean Chalard mPendingSuccessiveImsCallback = false; 396e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka resetPendingImsCallback(); 397e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_PENDING_IMS_CALLBACK), 398e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka PENDING_IMS_CALLBACK_DURATION); 399e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka } 400e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 401e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka executePendingImsCallback(latinIme, editorInfo, restarting); 402e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka latinIme.onStartInputViewInternal(editorInfo, restarting); 403e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mAppliedEditorInfo = editorInfo; 404e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka } 40559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 40659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 40759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInputView(boolean finishingInput) { 40859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { 40959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Typically this is the first onFinishInputView after orientation changed. 41059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInputView = true; 41159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } else { 41259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 41359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputViewInternal(finishingInput); 414e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mAppliedEditorInfo = null; 41538f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 41638f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 417ffd156c77e93a54b704780b46886ba597d1c77cbTadashi G. Takaoka 41859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInput() { 41959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { 42059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Typically this is the first onFinishInput after orientation changed. 42159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInput = true; 42259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } else { 42359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 42459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka executePendingImsCallback(latinIme, null, false); 42559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputInternal(); 426ffd156c77e93a54b704780b46886ba597d1c77cbTadashi G. Takaoka } 427ffd156c77e93a54b704780b46886ba597d1c77cbTadashi G. Takaoka } 42838f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 42938f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 43089ffb212b469531db4a616afb9bb7ba6d2a56b50Jean Chalard public LatinIME() { 43189ffb212b469531db4a616afb9bb7ba6d2a56b50Jean Chalard super(); 43289ffb212b469531db4a616afb9bb7ba6d2a56b50Jean Chalard mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 43389ffb212b469531db4a616afb9bb7ba6d2a56b50Jean Chalard mKeyboardSwitcher = KeyboardSwitcher.getInstance(); 43489ffb212b469531db4a616afb9bb7ba6d2a56b50Jean Chalard } 43589ffb212b469531db4a616afb9bb7ba6d2a56b50Jean Chalard 4367e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 4377e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka public void onCreate() { 43827d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 43927d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mPrefs = prefs; 44027d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa LatinImeLogger.init(this, prefs); 4416d9021527a38ba1e94225020389621a0d7227aa1satok LanguageSwitcherProxy.init(this, prefs); 442bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka InputMethodManagerCompatWrapper.init(this); 443ef5dfc480c7a3e3e34a20b7aacc731942e7a0578Tadashi G. Takaoka SubtypeSwitcher.init(this); 44427d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa KeyboardSwitcher.init(this, prefs); 4452ac5988f84b5c38d313951a3d7faddebf5f25e04Tadashi G. Takaoka AccessibilityUtils.init(this); 446363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 447923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onCreate(); 448363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 449bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka mImm = InputMethodManagerCompatWrapper.getInstance(); 45010dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka mHandler.onCreate(); 4519e2d810dc524380ca1db6b384cfb00b4401585e5Tadashi G. Takaoka DEBUG = LatinImeLogger.sDBG; 452363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 453363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka final Resources res = getResources(); 454363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka mResources = res; 455fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard 45628f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa loadSettings(); 45728f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa 458dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard // TODO: remove the following when it's not needed by updateCorrectionMode() any more 459644c8b7c96627199c13297082e4566adae159bf3Jean Chalard mInputAttributes = new InputAttributes(null, false /* isFullscreenMode */); 4603fe263fac6375836c48ce71da29f098b66eb4f11Jean Chalard updateCorrectionMode(); 4613fe263fac6375836c48ce71da29f098b66eb4f11Jean Chalard 4629502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Utils.GCUtils.getInstance().reset(); 463979f8690967ff5409fe18f5085858ccdb8e0ccf1satok boolean tryGC = true; 4649502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { 465979f8690967ff5409fe18f5085858ccdb8e0ccf1satok try { 4660ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 467979f8690967ff5409fe18f5085858ccdb8e0ccf1satok tryGC = false; 468979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } catch (OutOfMemoryError e) { 4699502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka tryGC = Utils.GCUtils.getInstance().tryGCOrWait("InitSuggest", e); 470979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 471979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 472979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 473f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka mDisplayOrientation = res.getConfiguration().orientation; 474b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 475cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Register to receive ringer mode change and network state change. 476cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Also receive installation and removal of a dictionary pack. 477123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final IntentFilter filter = new IntentFilter(); 478123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 47921af2f40c59de3ea5ec183aa278406bf28d5e3bdJean Chalard filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); 480923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project registerReceiver(mReceiver, filter); 481b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy = VoiceProxy.init(this, prefs, mHandler); 482cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 483cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final IntentFilter packageFilter = new IntentFilter(); 484cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 485cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 486cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addDataScheme(SCHEME_PACKAGE); 487cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard registerReceiver(mDictionaryPackInstallReceiver, packageFilter); 488646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard 489646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard final IntentFilter newDictFilter = new IntentFilter(); 490646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard newDictFilter.addAction( 491646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard DictionaryPackInstallBroadcastReceiver.NEW_DICTIONARY_INTENT_ACTION); 492646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard registerReceiver(mDictionaryPackInstallReceiver, newDictFilter); 493923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 49436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 49517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // Has to be package-visible for unit tests 49617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard /* package */ void loadSettings() { 49717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this); 4987a16a061e622539e54d7d649dcb8d4965aea575aJean Chalard mSettingsValues = new SettingsValues(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr()); 49921af2f40c59de3ea5ec183aa278406bf28d5e3bdJean Chalard mFeedbackManager = new AudioAndHapticFeedbackManager(this, mSettingsValues); 50014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary()); 50117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 50217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 5030ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private void initSuggest() { 504cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); 505ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr); 50636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 507309bff562fbaf47488e6bf6636840f00574187d8Jean Chalard final Resources res = mResources; 508ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard final Locale savedLocale = LocaleUtils.setSystemLocale(res, keyboardLocale); 50914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard final ContactsDictionary oldContactsDictionary; 51036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani if (mSuggest != null) { 51114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard oldContactsDictionary = mSuggest.getContactsDictionary(); 51236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mSuggest.close(); 51314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } else { 51414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard oldContactsDictionary = null; 51536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 516979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 517cc8c8b99bd0463f5977dea82f5e2379ea1dd4e73Tadashi G. Takaoka int mainDicResId = DictionaryFactory.getMainDictionaryResourceId(res); 518cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mSuggest = new Suggest(this, mainDicResId, keyboardLocale); 51917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.mAutoCorrectEnabled) { 52017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); 52117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 522e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 523cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mUserDictionary = new UserDictionary(this, localeStr); 524923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mSuggest.setUserDictionary(mUserDictionary); 52588562bec54658840dcce352127bdc15705c20a89Jean Chalard mIsUserDictionaryAvailable = mUserDictionary.isEnabled(); 526e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 52714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard resetContactsDictionary(oldContactsDictionary); 528e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 529c68d1bbfafe4b2041db49523c044123f78d6635dJean Chalard // TODO: rename UserBigramDictionary into UserHistoryDictionary 530f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard mUserBigramDictionary 531f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard = new UserBigramDictionary(this, this, localeStr, Suggest.DIC_USER_BIGRAM); 532c68d1bbfafe4b2041db49523c044123f78d6635dJean Chalard mSuggest.setUserUnigramDictionary(mUserBigramDictionary); 533e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.setUserBigramDictionary(mUserBigramDictionary); 534e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 535ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard LocaleUtils.setSystemLocale(res, savedLocale); 536923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 53736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 53814051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard /** 53914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * Resets the contacts dictionary in mSuggest according to the user settings. 54014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * 54114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * This method takes an optional contacts dictionary to use. Since the contacts dictionary 54214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * does not depend on the locale, it can be reused across different instances of Suggest. 54314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * The dictionary will also be opened or closed as necessary depending on the settings. 54414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * 54514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * @param oldContactsDictionary an optional dictionary to use, or null 54614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard */ 54714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard private void resetContactsDictionary(final ContactsDictionary oldContactsDictionary) { 54814051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard final boolean shouldSetDictionary = (null != mSuggest && mSettingsValues.mUseContactsDict); 54914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard 55014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard final ContactsDictionary dictionaryToUse; 55114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (!shouldSetDictionary) { 55214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // Make sure the dictionary is closed. If it is already closed, this is a no-op, 55314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // so it's safe to call it anyways. 55414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (null != oldContactsDictionary) oldContactsDictionary.close(); 55514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard dictionaryToUse = null; 55614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } else if (null != oldContactsDictionary) { 55714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // Make sure the old contacts dictionary is opened. If it is already open, this is a 55814051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // no-op, so it's safe to call it anyways. 55914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard oldContactsDictionary.reopen(this); 56014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard dictionaryToUse = oldContactsDictionary; 56114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } else { 56214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard dictionaryToUse = new ContactsDictionary(this, Suggest.DIC_CONTACTS); 56314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } 56414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard 56514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (null != mSuggest) { 56614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard mSuggest.setContactsDictionary(dictionaryToUse); 56714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } 568699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard } 569699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard 570cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard /* package private */ void resetSuggestMainDict() { 571cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); 572ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr); 573cc8c8b99bd0463f5977dea82f5e2379ea1dd4e73Tadashi G. Takaoka int mainDicResId = DictionaryFactory.getMainDictionaryResourceId(mResources); 574cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mSuggest.resetMainDict(this, mainDicResId, keyboardLocale); 575cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard } 576cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 577466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 578466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onDestroy() { 579e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa if (mSuggest != null) { 580e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.close(); 581e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest = null; 582979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 583923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project unregisterReceiver(mReceiver); 584cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard unregisterReceiver(mDictionaryPackInstallReceiver); 585b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.destroy(); 586979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 587979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.onDestroy(); 588923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onDestroy(); 589923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 590923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 591923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 592923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onConfigurationChanged(Configuration conf) { 593dc64b138b5e3fb3706c0818d0a308fe6e36985b0Tadashi G. Takaoka mSubtypeSwitcher.onConfigurationChanged(conf); 594b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani // If orientation changed while predicting, commit the change 595f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka if (mDisplayOrientation != conf.orientation) { 596f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka mDisplayOrientation = conf.orientation; 597f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka mHandler.startOrientationChanging(); 5989351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 59966bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitTyped(ic, LastComposedWord.NOT_A_SEPARATOR); 600466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (ic != null) ic.finishComposingText(); // For voice input 6012fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka if (isShowingOptionDialog()) 6022fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka mOptionsDialog.dismiss(); 603b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 6048b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 6053cd1a00ecacf01f3005e794f01be46648707c741Jean Chalard mVoiceProxy.startChangingConfiguration(); 606923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onConfigurationChanged(conf); 607b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.onConfigurationChanged(conf); 6083cd1a00ecacf01f3005e794f01be46648707c741Jean Chalard mVoiceProxy.finishChangingConfiguration(); 60988fc9d44186120f9edc5cf7ec0e2af85260fed04satok 61088fc9d44186120f9edc5cf7ec0e2af85260fed04satok // This will work only when the subtype is not supported. 61188fc9d44186120f9edc5cf7ec0e2af85260fed04satok LanguageSwitcherProxy.onConfigurationChanged(conf); 612923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 613b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 614923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 615923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public View onCreateInputView() { 6166c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka return mKeyboardSwitcher.onCreateInputView(); 6176c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka } 6186c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka 6196c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka @Override 6206c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka public void setInputView(View view) { 6216c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka super.setInputView(view); 622d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka mExtractArea = getWindow().getWindow().getDecorView() 623d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka .findViewById(android.R.id.extractArea); 624abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka mKeyPreviewBackingView = view.findViewById(R.id.key_preview_backing); 625913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsContainer = view.findViewById(R.id.suggestions_container); 626913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView = (SuggestionsView) view.findViewById(R.id.suggestions_view); 627913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) 628913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.setListener(this, view); 629f5fe245df0548ea0a8ec607f2392de0fe02c141dTadashi G. Takaoka if (LatinImeLogger.sVISUALDEBUG) { 630f5fe245df0548ea0a8ec607f2392de0fe02c141dTadashi G. Takaoka mKeyPreviewBackingView.setBackgroundColor(0x10FF0000); 631f5fe245df0548ea0a8ec607f2392de0fe02c141dTadashi G. Takaoka } 632923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 633923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 634923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 635c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka public void setCandidatesView(View view) { 636c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka // To ensure that CandidatesView will never be set. 637c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return; 638923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 639923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 640a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker @Override 641e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka public void onStartInput(EditorInfo editorInfo, boolean restarting) { 642e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mHandler.onStartInput(editorInfo, restarting); 64359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 64459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 64559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka @Override 646e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka public void onStartInputView(EditorInfo editorInfo, boolean restarting) { 647e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mHandler.onStartInputView(editorInfo, restarting); 64859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 64959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 65059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka @Override 65159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInputView(boolean finishingInput) { 65259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHandler.onFinishInputView(finishingInput); 65359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 65438f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 65559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka @Override 65659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInput() { 65759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHandler.onFinishInput(); 65859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 65959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 660e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka private void onStartInputInternal(EditorInfo editorInfo, boolean restarting) { 661e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka super.onStartInput(editorInfo, restarting); 66259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 66359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 664e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka private void onStartInputViewInternal(EditorInfo editorInfo, boolean restarting) { 665e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka super.onStartInputView(editorInfo, restarting); 66645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 667c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka LatinKeyboardView inputView = switcher.getKeyboardView(); 6688e09172df1bb176cc899940862c56bed9b9aec4esatok 669ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok if (editorInfo == null) { 670ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok Log.e(TAG, "Null EditorInfo in onStartInputView()"); 671ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok if (LatinImeLogger.sDBG) { 672ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok throw new NullPointerException("Null EditorInfo in onStartInputView()"); 673ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok } 674ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok return; 675ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok } 67689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (DEBUG) { 677ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok Log.d(TAG, "onStartInputView: editorInfo:" 678ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok + String.format("inputType=0x%08x imeOptions=0x%08x", 679ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok editorInfo.inputType, editorInfo.imeOptions)); 680910b73127fa207dd26ec8124000262523b0aac0csatok } 681cc8c8b99bd0463f5977dea82f5e2379ea1dd4e73Tadashi G. Takaoka if (StringUtils.inPrivateImeOptions(null, IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo)) { 6824f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka Log.w(TAG, "Deprecated private IME option specified: " 6834f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka + editorInfo.privateImeOptions); 6844f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka Log.w(TAG, "Use " + getPackageName() + "." + IME_OPTION_NO_MICROPHONE + " instead"); 6854f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka } 686cc8c8b99bd0463f5977dea82f5e2379ea1dd4e73Tadashi G. Takaoka if (StringUtils.inPrivateImeOptions(getPackageName(), IME_OPTION_FORCE_ASCII, editorInfo)) { 6874f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka Log.w(TAG, "Deprecated private IME option specified: " 6884f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka + editorInfo.privateImeOptions); 6894f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka Log.w(TAG, "Use EditorInfo.IME_FLAG_FORCE_ASCII flag instead"); 6904f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka } 6914f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka 6927ef235f53f2291f22ddf8c56be9860a218b25bbbTadashi G. Takaoka LatinImeLogger.onStartInputView(editorInfo); 693923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In landscape mode, this method gets called without the input view being created. 694979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (inputView == null) { 695923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 696923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 697923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 698b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette // Forward this event to the accessibility utilities, if enabled. 699b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette final AccessibilityUtils accessUtils = AccessibilityUtils.getInstance(); 700b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette if (accessUtils.isTouchExplorationEnabled()) { 701e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka accessUtils.onStartInputViewInternal(editorInfo, restarting); 702b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette } 703b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette 7048d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka mSubtypeSwitcher.updateParametersOnStartInputView(); 7054ab730dbd34fad323063f2ffd31ce33de746668dsatok 706055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka // Most such things we decide below in initializeInputAttributesAndGetMode, but we need to 707055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka // know now whether this is a password text field, because we need to know now whether we 708055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka // want to enable the voice button. 709ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok final int inputType = editorInfo.inputType; 710104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard mVoiceProxy.resetVoiceStates(InputTypeCompatUtils.isPasswordInputType(inputType) 7113be0039164f5e2060b83d0699e293ffc76384732Tadashi G. Takaoka || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)); 712c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 713b2b1eb5ca5a52648eea70920b9bd745b07d3ddfaTadashi G. Takaoka // The EditorInfo might have a flag that affects fullscreen mode. 714b2b1eb5ca5a52648eea70920b9bd745b07d3ddfaTadashi G. Takaoka // Note: This call should be done by InputMethodService? 715b2b1eb5ca5a52648eea70920b9bd745b07d3ddfaTadashi G. Takaoka updateFullscreenMode(); 7161fead1d5f12928f90c723b5f7b88490cc7cd2a67Jean Chalard mLastSelectionStart = editorInfo.initialSelStart; 7171fead1d5f12928f90c723b5f7b88490cc7cd2a67Jean Chalard mLastSelectionEnd = editorInfo.initialSelEnd; 71880b66bb166f7f45adfcadcb84788477df9930828Jean Chalard mInputAttributes = new InputAttributes(editorInfo, isFullscreenMode()); 719ccc35f7fa74860a8d737a4e9ff01fc0168dd329dJean Chalard mApplicationSpecifiedCompletions = null; 720c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 721c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.closing(); 722c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mEnteredText = null; 7232692a8700737d8eed268039aa27b22a31669da08Jean Chalard resetComposingState(true /* alsoResetLastComposedWord */); 724c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mDeleteCount = 0; 725120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 726c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 72717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 72817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard updateCorrectionMode(); 7292ac5988f84b5c38d313951a3d7faddebf5f25e04Tadashi G. Takaoka updateSuggestionVisibility(mResources); 73017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 73117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSuggest != null && mSettingsValues.mAutoCorrectEnabled) { 73217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); 733549e295dc113bff50077c3c355dcd94af09a1b2fTadashi G. Takaoka } 734e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mVoiceProxy.loadSettings(editorInfo, mPrefs); 73517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // This will work only when the subtype is not supported. 73617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard LanguageSwitcherProxy.loadSettings(); 73717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 738c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (mSubtypeSwitcher.isKeyboardMode()) { 739e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka switcher.loadKeyboard(editorInfo, mSettingsValues); 740c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 741c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 742913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) 743913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.clear(); 744913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShownInternal( 745913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka isSuggestionsStripVisible(), /* needsInputViewShown */ false); 746c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // Delay updating suggestions because keyboard input view may not be shown at this point. 747c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mHandler.postUpdateSuggestions(); 748ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa mHandler.cancelDoubleSpacesTimer(); 749c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 750240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard inputView.setKeyPreviewPopupEnabled(mSettingsValues.mKeyPreviewPopupOn, 751240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard mSettingsValues.mKeyPreviewPopupDismissDelay); 752c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.setProximityCorrectionEnabled(true); 753c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 754104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard mVoiceProxy.onStartInputView(inputView.getWindowToken()); 755c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 756c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); 757c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 758c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 759923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 760e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka public void onWindowHidden() { 761e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka super.onWindowHidden(); 762f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 763e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka if (inputView != null) inputView.closing(); 764e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka } 765e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka 76659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void onFinishInputInternal() { 767923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onFinishInput(); 768a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 769979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 770979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 7713cd1a00ecacf01f3005e794f01be46648707c741Jean Chalard mVoiceProxy.flushVoiceInputLogs(); 772409220583333bdf06290dd9fd42f91b5c0d1b11asatok 773f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 774d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa if (inputView != null) inputView.closing(); 775979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mUserBigramDictionary != null) mUserBigramDictionary.flushPendingWrites(); 776466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 777466741d8a78965b8509bf527344f289e50873092Mike LeBeau 77859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void onFinishInputViewInternal(boolean finishingInput) { 7796495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa super.onFinishInputView(finishingInput); 780055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka mKeyboardSwitcher.onFinishInputView(); 781f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 7825f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka if (inputView != null) inputView.cancelAllMessages(); 783d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka // Remove pending messages related to update suggestions 784d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 7856495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa } 7866495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa 7876495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa @Override 788466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onUpdateExtractedText(int token, ExtractedText text) { 789466741d8a78965b8509bf527344f289e50873092Mike LeBeau super.onUpdateExtractedText(token, text); 790b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.showPunctuationHintIfNecessary(); 791923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 792923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 793923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 794923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onUpdateSelection(int oldSelStart, int oldSelEnd, 795923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int newSelStart, int newSelEnd, 796104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard int composingSpanStart, int composingSpanEnd) { 797923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, 798104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard composingSpanStart, composingSpanEnd); 799466741d8a78965b8509bf527344f289e50873092Mike LeBeau 800466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (DEBUG) { 801466741d8a78965b8509bf527344f289e50873092Mike LeBeau Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart 802466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ose=" + oldSelEnd 803025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lss=" + mLastSelectionStart 804025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lse=" + mLastSelectionEnd 805466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nss=" + newSelStart 806466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nse=" + newSelEnd 807104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard + ", cs=" + composingSpanStart 808104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard + ", ce=" + composingSpanEnd); 809466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 810466741d8a78965b8509bf527344f289e50873092Mike LeBeau 811b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.setCursorAndSelection(newSelEnd, newSelStart); 8124f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 813104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // TODO: refactor the following code to be less contrived. 814104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // "newSelStart != composingSpanEnd" || "newSelEnd != composingSpanEnd" means 815104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // that the cursor is not at the end of the composing span, or there is a selection. 816104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // "mLastSelectionStart != newSelStart" means that the cursor is not in the same place 817104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // as last time we were called (if there is a selection, it means the start hasn't 818104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // changed, so it's the end that did). 819104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard final boolean selectionChanged = (newSelStart != composingSpanEnd 820104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard || newSelEnd != composingSpanEnd) && mLastSelectionStart != newSelStart; 821104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // if composingSpanStart and composingSpanEnd are -1, it means there is no composing 822104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // span in the view - we can use that to narrow down whether the cursor was moved 823104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // by us or not. If we are composing a word but there is no composing span, then 824104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // we know for sure the cursor moved while we were composing and we should reset 825104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // the state. 826104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard final boolean noComposingSpan = composingSpanStart == -1 && composingSpanEnd == -1; 8274733609947c0ec74e460bd714fffca0518ade93aJean Chalard if (!mExpectingUpdateSelection) { 828cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard // TAKE CARE: there is a race condition when we enter this test even when the user 829cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard // did not explicitly move the cursor. This happens when typing fast, where two keys 830cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard // turn this flag on in succession and both onUpdateSelection() calls arrive after 831cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard // the second one - the first call successfully avoids this test, but the second one 832104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // enters. For the moment we rely on noComposingSpan to further reduce the impact. 83351fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard 8349a2a11e65bd32d82754b3fcff74e9e3795327628Jean Chalard // TODO: the following is probably better done in resetEntireInputState(). 8359a2a11e65bd32d82754b3fcff74e9e3795327628Jean Chalard // it should only happen when the cursor moved, and the very purpose of the 8369a2a11e65bd32d82754b3fcff74e9e3795327628Jean Chalard // test below is to narrow down whether this happened or not. Likewise with 8379a2a11e65bd32d82754b3fcff74e9e3795327628Jean Chalard // the call to postUpdateShiftState. 83851fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard // We set this to NONE because after a cursor move, we don't want the space 83951fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard // state-related special processing to kick in. 84051fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard mSpaceState = SPACE_STATE_NONE; 84151fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard 8428a3d369840d6061692a19ceb1eb7267a50a9e056Jean Chalard if ((!mWordComposer.isComposingWord()) || selectionChanged || noComposingSpan) { 8432649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard resetEntireInputState(); 8444c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard } 845beb08b398fa73a26f2d42d6feec87e34a96ca2d9Tadashi G. Takaoka 846beb08b398fa73a26f2d42d6feec87e34a96ca2d9Tadashi G. Takaoka mHandler.postUpdateShiftState(); 8474733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 8484733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = false; 8496b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // TODO: Decide to call restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() or not 8506b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // here. It would probably be too expensive to call directly here but we may want to post a 8516b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // message to delay it. The point would be to unify behavior between backspace to the 8526b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // end of a word and manually put the pointer at the end of the word. 853466741d8a78965b8509bf527344f289e50873092Mike LeBeau 854979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Make a note of the cursor position 855979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionStart = newSelStart; 856979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionEnd = newSelEnd; 8577a8dac55278cedd838be325f56b4c52d973c61f5satok } 8587a8dac55278cedd838be325f56b4c52d973c61f5satok 859c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 860c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has clicked on the extracted text view, 861c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * when running in fullscreen mode. The default implementation hides 862913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * the suggestions view when this happens, but only if the extracted text 863c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * editor has a vertical scroll bar because its text doesn't fit. 864c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 865913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * cause the suggestions strip to disappear and re-appear. 866c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 867c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 868c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedTextClicked() { 869fe5364c825058f6c34c0f42135a5520b77525a28Jean Chalard if (isSuggestionsRequested()) return; 870c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 871c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedTextClicked(); 872c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 873c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 874c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 875c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has performed a cursor movement in the 876c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * extracted text view, when it is running in fullscreen mode. The default 877913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * implementation hides the suggestions view when a vertical movement 878c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * happens, but only if the extracted text editor has a vertical scroll bar 879c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * because its text doesn't fit. 880c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 881913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * cause the suggestions strip to disappear and re-appear. 882c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 883c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 884c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedCursorMovement(int dx, int dy) { 885fe5364c825058f6c34c0f42135a5520b77525a28Jean Chalard if (isSuggestionsRequested()) return; 886c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 887c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedCursorMovement(dx, dy); 888c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 889c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 890923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 891923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void hideWindow() { 892979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 893c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka mKeyboardSwitcher.onHideWindow(); 894979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 895923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (TRACE) Debug.stopMethodTracing(); 8966e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mOptionsDialog != null && mOptionsDialog.isShowing()) { 8976e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog.dismiss(); 8986e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog = null; 8996e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 9003cd1a00ecacf01f3005e794f01be46648707c741Jean Chalard mVoiceProxy.hideVoiceWindow(); 901923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.hideWindow(); 902923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 903923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 904923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 9051b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka public void onDisplayCompletions(CompletionInfo[] applicationSpecifiedCompletions) { 906979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (DEBUG) { 907a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa Log.i(TAG, "Received completions:"); 908bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok if (applicationSpecifiedCompletions != null) { 909bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok for (int i = 0; i < applicationSpecifiedCompletions.length; i++) { 910bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok Log.i(TAG, " #" + i + ": " + applicationSpecifiedCompletions[i]); 911bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok } 912923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 913923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 914dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard if (mInputAttributes.mApplicationSpecifiedCompletionOn) { 9151b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletions = applicationSpecifiedCompletions; 9161b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (applicationSpecifiedCompletions == null) { 917b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani clearSuggestions(); 918923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 919923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 920a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 921660776e09b9a3b321074a94721d901a035ca1b9fKen Wakasa final ArrayList<SuggestedWords.SuggestedWordInfo> applicationSuggestedWords = 92288bf1ba5263f5a5c1df367ddc401db4109ef8677Jean Chalard SuggestedWords.getFromApplicationSpecifiedCompletions( 9231dfef0336d5968dbd00b73489778cee1fb233d56Jean Chalard applicationSpecifiedCompletions); 924bdf6d1b18b3cebdde5f39d10066ead34be161bafJean Chalard final SuggestedWords suggestedWords = new SuggestedWords( 9257d55c891afdf7e74e505acac998a95a9ca7a9ec2Jean Chalard applicationSuggestedWords, 9262e2519ee914d4bf9462950553840557a4c19faedJean Chalard false /* typedWordValid */, 927bdf6d1b18b3cebdde5f39d10066ead34be161bafJean Chalard false /* hasAutoCorrectionCandidate */, 928b5eeb724fc98bb7169683539027d9ba54ffb8b14Jean Chalard false /* allowsToBeAutoCorrected */, 92903a35170751a635332c00bf6c272a0127a255cf6Jean Chalard false /* isPunctuationSuggestions */, 93003a35170751a635332c00bf6c272a0127a255cf6Jean Chalard false /* isObsoleteSuggestions */); 931979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // When in fullscreen mode, show completions generated by the application 9324e112d07821d34c1dedd21b086817be9fce2fd47Jean Chalard final boolean isAutoCorrection = false; 9337d55c891afdf7e74e505acac998a95a9ca7a9ec2Jean Chalard setSuggestions(suggestedWords, isAutoCorrection); 934dd931c47be1a4fe4cf86c8ad018e479c2cbdf8ceJean Chalard setAutoCorrectionIndicator(isAutoCorrection); 935b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard // TODO: is this the right thing to do? What should we auto-correct to in 936b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard // this case? This says to keep whatever the user typed. 937b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard mWordComposer.setAutoCorrection(mWordComposer.getTypedWord()); 938c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShown(true); 939923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 940923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 941923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 942c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka private void setSuggestionStripShownInternal(boolean shown, boolean needsInputViewShown) { 943913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka // TODO: Modify this if we support suggestions with hard keyboard 944913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (onEvaluateInputViewShown() && mSuggestionsContainer != null) { 945433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka final LatinKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); 946433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka final boolean inputViewShown = (keyboardView != null) ? keyboardView.isShown() : false; 947913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka final boolean shouldShowSuggestions = shown 948433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka && (needsInputViewShown ? inputViewShown : true); 9494b1780fa9571409d65d9797d47949ffafaf0f083Tadashi G. Takaoka if (isFullscreenMode()) { 950913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsContainer.setVisibility( 951913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka shouldShowSuggestions ? View.VISIBLE : View.GONE); 9527a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka } else { 953913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsContainer.setVisibility( 954913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka shouldShowSuggestions ? View.VISIBLE : View.INVISIBLE); 9557a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka } 956923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 957923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 958a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 959c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka private void setSuggestionStripShown(boolean shown) { 960c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShownInternal(shown, /* needsInputViewShown */true); 961543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa } 962543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa 963c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka private void adjustInputViewHeight() { 964c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka if (mKeyPreviewBackingView.getHeight() > 0) { 965c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka return; 966c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka } 967c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka 968c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka final KeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); 969c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka if (keyboardView == null) return; 970c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka final int keyboardHeight = keyboardView.getHeight(); 971c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka final int suggestionsHeight = mSuggestionsContainer.getHeight(); 972c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka final int displayHeight = mResources.getDisplayMetrics().heightPixels; 973c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka final Rect rect = new Rect(); 974c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka mKeyPreviewBackingView.getWindowVisibleDisplayFrame(rect); 975c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka final int notificationBarHeight = rect.top; 976c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka final int remainingHeight = displayHeight - notificationBarHeight - suggestionsHeight 977c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka - keyboardHeight; 978c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka 979c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka final LayoutParams params = mKeyPreviewBackingView.getLayoutParams(); 980c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka params.height = mSuggestionsView.setMoreSuggestionsHeight(remainingHeight); 981c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka mKeyPreviewBackingView.setLayoutParams(params); 982c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka } 983c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka 984543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa @Override 985923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onComputeInsets(InputMethodService.Insets outInsets) { 986923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onComputeInsets(outInsets); 987f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka final KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 988913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (inputView == null || mSuggestionsContainer == null) 98946ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka return; 990c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka adjustInputViewHeight(); 991d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka // In fullscreen mode, the height of the extract area managed by InputMethodService should 992d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka // be considered. 993d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka // See {@link android.inputmethodservice.InputMethodService#onComputeInsets}. 994d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka final int extractHeight = isFullscreenMode() ? mExtractArea.getHeight() : 0; 995abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka final int backingHeight = (mKeyPreviewBackingView.getVisibility() == View.GONE) ? 0 996abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka : mKeyPreviewBackingView.getHeight(); 99759010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka final int suggestionsHeight = (mSuggestionsContainer.getVisibility() == View.GONE) ? 0 99859010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka : mSuggestionsContainer.getHeight(); 999d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka final int extraHeight = extractHeight + backingHeight + suggestionsHeight; 1000abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka int touchY = extraHeight; 10019e347d3d448e48229c46aad394ec9bd60cd5807bsatok // Need to set touchable region only if input view is being shown 1002433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka final LatinKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); 1003433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka if (keyboardView != null && keyboardView.isShown()) { 1004913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsContainer.getVisibility() == View.VISIBLE) { 100559010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka touchY -= suggestionsHeight; 10069e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 10077a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka final int touchWidth = inputView.getWidth(); 1008abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka final int touchHeight = inputView.getHeight() + extraHeight 10097a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // Extend touchable region below the keyboard. 10107a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka + EXTENDED_TOUCHABLE_REGION_HEIGHT; 10119e347d3d448e48229c46aad394ec9bd60cd5807bsatok if (DEBUG) { 10127a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka Log.d(TAG, "Touchable region: y=" + touchY + " width=" + touchWidth 10137a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka + " height=" + touchHeight); 10149e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 10157a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka setTouchableRegionCompat(outInsets, 0, touchY, touchWidth, touchHeight); 10169e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 101746ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka outInsets.contentTopInsets = touchY; 101846ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka outInsets.visibleTopInsets = touchY; 1019923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1020a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1021923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 1022979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public boolean onEvaluateFullscreenMode() { 10239751a626ec9b2e771afa5b3757e8f8498a328683Tadashi G. Takaoka // Reread resource value here, because this method is called by framework anytime as needed. 10249751a626ec9b2e771afa5b3757e8f8498a328683Tadashi G. Takaoka final boolean isFullscreenModeAllowed = 10259751a626ec9b2e771afa5b3757e8f8498a328683Tadashi G. Takaoka mSettingsValues.isFullscreenModeAllowed(getResources()); 10269751a626ec9b2e771afa5b3757e8f8498a328683Tadashi G. Takaoka return super.onEvaluateFullscreenMode() && isFullscreenModeAllowed; 102759010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka } 102859010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka 102959010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka @Override 103059010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka public void updateFullscreenMode() { 103159010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka super.updateFullscreenMode(); 1032f80b6a06992ae08ca3601f4fbc6da550fd9ac730Tadashi G. Takaoka 103359010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka if (mKeyPreviewBackingView == null) return; 1034549e295dc113bff50077c3c355dcd94af09a1b2fTadashi G. Takaoka // In fullscreen mode, no need to have extra space to show the key preview. 103559010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka // If not, we should have extra space above the keyboard to show the key preview. 1036549e295dc113bff50077c3c355dcd94af09a1b2fTadashi G. Takaoka mKeyPreviewBackingView.setVisibility(isFullscreenMode() ? View.GONE : View.VISIBLE); 1037979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1038979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1039979f8690967ff5409fe18f5085858ccdb8e0ccf1satok @Override 1040923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 1041923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 1042e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_BACK: 10432cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka if (event.getRepeatCount() == 0) { 10442cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka if (mSuggestionsView != null && mSuggestionsView.handleBack()) { 10452cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka return true; 10462cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka } 10472cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka final LatinKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); 10482cb36637f41418e4037023a47915dd64a30ab869Tadashi G. Takaoka if (keyboardView != null && keyboardView.handleBack()) { 10496e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani return true; 10506e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 1051e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 1052e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 1053923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1054923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyDown(keyCode, event); 1055923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1056923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1057923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 1058923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 1059923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 1060e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_DOWN: 1061e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_UP: 1062e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_LEFT: 1063e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_RIGHT: 1064433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka final LatinKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); 1065433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); 1066e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka // Enable shift key and DPAD to do selections 1067433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka if ((keyboardView != null && keyboardView.isShown()) 1068433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka && (keyboard != null && keyboard.isShiftedOrShiftLocked())) { 1069e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent newEvent = new KeyEvent(event.getDownTime(), event.getEventTime(), 1070e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getAction(), event.getKeyCode(), event.getRepeatCount(), 1071e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getDeviceId(), event.getScanCode(), 1072e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON); 10739351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1074e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (ic != null) 1075e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka ic.sendKeyEvent(newEvent); 1076e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka return true; 1077e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 1078e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 1079923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1080923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyUp(keyCode, event); 1081923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1082923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 10832649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard // This will reset the whole input state to the starting state. It will clear 10842649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard // the composing word, reset the last composed word, tell the inputconnection 10852649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard // and the composingStateManager about it. 10862649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard private void resetEntireInputState() { 10872649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard resetComposingState(true /* alsoResetLastComposedWord */); 10882649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard updateSuggestions(); 10892649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard final InputConnection ic = getCurrentInputConnection(); 10902649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard if (ic != null) { 10912649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard ic.finishComposingText(); 10922649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard } 10932649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard mVoiceProxy.setVoiceInputHighlighted(false); 10942649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard } 10952649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard 10962692a8700737d8eed268039aa27b22a31669da08Jean Chalard private void resetComposingState(final boolean alsoResetLastComposedWord) { 10972692a8700737d8eed268039aa27b22a31669da08Jean Chalard mWordComposer.reset(); 10982692a8700737d8eed268039aa27b22a31669da08Jean Chalard if (alsoResetLastComposedWord) 10992692a8700737d8eed268039aa27b22a31669da08Jean Chalard mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; 11002692a8700737d8eed268039aa27b22a31669da08Jean Chalard } 11012692a8700737d8eed268039aa27b22a31669da08Jean Chalard 110266bb563535dbe3672f99f75bd71763a551444867Jean Chalard public void commitTyped(final InputConnection ic, final int separatorCode) { 1103196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (!mWordComposer.isComposingWord()) return; 11043651220327c051d8017045aa5e8919461507b3f8Jean Chalard final CharSequence typedWord = mWordComposer.getTypedWord(); 11053651220327c051d8017045aa5e8919461507b3f8Jean Chalard if (typedWord.length() > 0) { 1106cf9d92629cae88273805eaf7984fcfdd8afd11f5Jean Chalard mLastComposedWord = mWordComposer.commitWord( 110766bb563535dbe3672f99f75bd71763a551444867Jean Chalard LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, typedWord.toString(), 110866bb563535dbe3672f99f75bd71763a551444867Jean Chalard separatorCode); 11099351550dc6af7859e5280e16144c9386a37b976dKen Wakasa if (ic != null) { 11103651220327c051d8017045aa5e8919461507b3f8Jean Chalard ic.commitText(typedWord, 1); 1111923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1112c24f66e18007b5aba32bfab8f86eb7f03fa6c1b7Jean Chalard addToUserHistoryDictionary(typedWord); 1113923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 11148558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa updateSuggestions(); 1115923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1116923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1117b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public boolean getCurrentAutoCapsState() { 11189351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 11191c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani EditorInfo ei = getCurrentInputEditorInfo(); 112017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.mAutoCap && ic != null && ei != null 112117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && ei.inputType != InputType.TYPE_NULL) { 1122b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return ic.getCursorCapsMode(ei.inputType) != 0; 11231c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 1124b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 11251c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 11261c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 1127b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard // "ic" may be null 1128b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard private void swapSwapperAndSpaceWhileInBatchEdit(final InputConnection ic) { 1129b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard if (null == ic) return; 1130923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence lastTwo = ic.getTextBeforeCursor(2, 0); 1131863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called. 1132923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastTwo != null && lastTwo.length() == 2 1133863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard && lastTwo.charAt(0) == Keyboard.CODE_SPACE) { 1134923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 1135923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(lastTwo.charAt(1) + " ", 1); 1136b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 11374ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 11384ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 11394ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1140120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private boolean maybeDoubleSpaceWhileInBatchEdit(final InputConnection ic) { 1141120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (mCorrectionMode == Suggest.CORRECTION_NONE) return false; 1142120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (ic == null) return false; 11432b4eabed2bfe982b91a994c145401d98894e6ef5Jean Chalard final CharSequence lastThree = ic.getTextBeforeCursor(3, 0); 1144923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastThree != null && lastThree.length() == 3 1145cc8c8b99bd0463f5977dea82f5e2379ea1dd4e73Tadashi G. Takaoka && StringUtils.canBeFollowedByPeriod(lastThree.charAt(0)) 1146571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(1) == Keyboard.CODE_SPACE 1147fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka && lastThree.charAt(2) == Keyboard.CODE_SPACE 1148fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka && mHandler.isAcceptingDoubleSpaces()) { 1149fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka mHandler.cancelDoubleSpacesTimer(); 1150923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 1151923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(". ", 1); 1152b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1153120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return true; 1154923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1155120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return false; 1156923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1157a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1158b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard // "ic" may be null 11598fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka private static void removeTrailingSpaceWhileInBatchEdit(final InputConnection ic) { 11609a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic == null) return; 1161b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard final CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 11629a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (lastOne != null && lastOne.length() == 1 1163571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastOne.charAt(0) == Keyboard.CODE_SPACE) { 11649a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.deleteSurroundingText(1, 0); 11659a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 11669a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 11679a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa 1168c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka @Override 1169923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean addWordToDictionary(String word) { 1170923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mUserDictionary.addWord(word, 128); 11716558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Suggestion strip should be updated after the operation of adding word to the 11726558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // user dictionary 1173d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1174923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1175923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1176923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 11778fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka private static boolean isAlphabet(int code) { 11788fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka return Character.isLetter(code); 1179923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1180a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1181e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka private void onSettingsKeyPressed() { 1182cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa if (isShowingOptionDialog()) return; 1183d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) { 1184d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka showSubtypeSelectorAndSettings(); 1185cc8c8b99bd0463f5977dea82f5e2379ea1dd4e73Tadashi G. Takaoka } else if (SubtypeUtils.hasMultipleEnabledIMEsOrSubtypes( 1186cc8c8b99bd0463f5977dea82f5e2379ea1dd4e73Tadashi G. Takaoka false /* exclude aux subtypes */)) { 1187d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka showOptionsMenu(); 1188d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka } else { 1189d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka launchSettings(); 11909a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 11919a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 11929a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 1193cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa // Virtual codes representing custom requests. These are used in onCustomRequest() below. 1194cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa public static final int CODE_SHOW_INPUT_METHOD_PICKER = 1; 1195d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka public static final int CODE_HAPTIC_AND_AUDIO_FEEDBACK = 2; 1196cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa 1197cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa @Override 1198cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa public boolean onCustomRequest(int requestCode) { 1199cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa if (isShowingOptionDialog()) return false; 1200cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa switch (requestCode) { 1201cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa case CODE_SHOW_INPUT_METHOD_PICKER: 1202cc8c8b99bd0463f5977dea82f5e2379ea1dd4e73Tadashi G. Takaoka if (SubtypeUtils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */)) { 120379efbed76f638be298493107fa2d0cd1b5eb529esatok mImm.showInputMethodPicker(); 1204cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return true; 12059a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 1206cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return false; 1207d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka case CODE_HAPTIC_AND_AUDIO_FEEDBACK: 1208d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka hapticAndAudioFeedback(Keyboard.CODE_UNSPECIFIED); 1209d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka return true; 12109a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 1211cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return false; 12129a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 12139a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 12149a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok private boolean isShowingOptionDialog() { 12159a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok return mOptionsDialog != null && mOptionsDialog.isShowing(); 12169a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 12179a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 121805bfd189a88be79ddfc74d0ea21792e2fb78f2aaTadashi G. Takaoka private static int getActionId(Keyboard keyboard) { 121905bfd189a88be79ddfc74d0ea21792e2fb78f2aaTadashi G. Takaoka return keyboard != null ? keyboard.mId.imeActionId() : EditorInfo.IME_ACTION_NONE; 12207a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 12217a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka 12227a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka private void performeEditorAction(int actionId) { 12237a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 12247a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka if (ic != null) { 12257a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka ic.performEditorAction(actionId); 12267a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 12277a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 12287a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka 122981d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka private void handleLanguageSwitchKey() { 1230c1ca8815f59bb1bce25e521571a1d87c71bf3fc3Ken Wakasa final boolean includesOtherImes = mSettingsValues.mIncludesOtherImesInLanguageSwitchList; 123181d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka final IBinder token = getWindow().getWindow().getAttributes().token; 123281d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka if (mShouldSwitchToLastSubtype) { 123381d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka final InputMethodSubtypeCompatWrapper lastSubtype = mImm.getLastInputMethodSubtype(); 1234cc8c8b99bd0463f5977dea82f5e2379ea1dd4e73Tadashi G. Takaoka final boolean lastSubtypeBelongsToThisIme = SubtypeUtils.checkIfSubtypeBelongsToThisIme( 123581d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka this, lastSubtype); 123681d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka if ((includesOtherImes || lastSubtypeBelongsToThisIme) 123781d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka && mImm.switchToLastInputMethod(token)) { 123881d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka mShouldSwitchToLastSubtype = false; 123981d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka } else { 124081d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka mImm.switchToNextInputMethod(token, !includesOtherImes); 124181d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka mShouldSwitchToLastSubtype = true; 124281d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka } 124381d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka } else { 124481d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka mImm.switchToNextInputMethod(token, !includesOtherImes); 124581d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka } 124681d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka } 124781d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka 12487a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka private void sendKeyCodePoint(int code) { 12497a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka // TODO: Remove this special handling of digit letters. 12507a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka // For backward compatibility. See {@link InputMethodService#sendKeyChar(char)}. 12517a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka if (code >= '0' && code <= '9') { 12527a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka super.sendKeyChar((char)code); 12537a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka return; 12547a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 12557a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka 12567a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 12577a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka if (ic != null) { 12587a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka final String text = new String(new int[] { code }, 0, 1); 12597a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka ic.commitText(text, text.length()); 12607a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 12617a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 12627a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka 12635f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // Implementation of {@link KeyboardActionListener}. 12645a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 1265ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok public void onCodeInput(int primaryCode, int x, int y) { 1266175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka final long when = SystemClock.uptimeMillis(); 1267571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) { 1268923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mDeleteCount = 0; 1269923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1270923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastKeyTime = when; 1271175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 1272120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // The space state depends only on the last character pressed and its own previous 1273120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // state. Here, we revert the space state to neutral if the key is actually modifying 1274120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // the input contents (any non-shift key), which is what we should do for 1275120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // all inputs that do not result in a special state. Each character handling is then 1276120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // free to override the state as they see fit. 1277120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final int spaceState = mSpaceState; 127870852c91dc7209d0aaa875a2cb0f79739c7398e6Jean Chalard if (!mWordComposer.isComposingWord()) mIsAutoCorrectionIndicatorOn = false; 1279ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa 1280ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa // TODO: Consolidate the double space timer, mLastKeyTime, and the space state. 1281ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa if (primaryCode != Keyboard.CODE_SPACE) { 1282ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa mHandler.cancelDoubleSpacesTimer(); 1283ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa } 1284ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa 1285c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard boolean didAutoCorrect = false; 1286923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 1287571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_DELETE: 1288120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 1289120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard handleBackspace(spaceState); 12904189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka mDeleteCount++; 12914733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 129281d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka mShouldSwitchToLastSubtype = true; 12934189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka LatinImeLogger.logOnDelete(); 12944189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1295571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_SHIFT: 1296e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: 12972a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka // Shift and symbol key is handled in onPressKey() and onReleaseKey(). 12984189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1299e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SETTINGS: 130093246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka onSettingsKeyPressed(); 13014189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1302d2c5fdda862f6dd2a1e020cf674c35fbbc63fc92Tadashi G. Takaoka case Keyboard.CODE_SHORTCUT: 130393246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka mSubtypeSwitcher.switchToShortcutIME(); 13044189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 13057a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka case Keyboard.CODE_ACTION_ENTER: 130605bfd189a88be79ddfc74d0ea21792e2fb78f2aaTadashi G. Takaoka performeEditorAction(getActionId(switcher.getKeyboard())); 13077a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka break; 130805bfd189a88be79ddfc74d0ea21792e2fb78f2aaTadashi G. Takaoka case Keyboard.CODE_ACTION_NEXT: 130905bfd189a88be79ddfc74d0ea21792e2fb78f2aaTadashi G. Takaoka performeEditorAction(EditorInfo.IME_ACTION_NEXT); 131005bfd189a88be79ddfc74d0ea21792e2fb78f2aaTadashi G. Takaoka break; 131105bfd189a88be79ddfc74d0ea21792e2fb78f2aaTadashi G. Takaoka case Keyboard.CODE_ACTION_PREVIOUS: 131205bfd189a88be79ddfc74d0ea21792e2fb78f2aaTadashi G. Takaoka EditorInfoCompatUtils.performEditorActionPrevious(getCurrentInputConnection()); 13134189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 131481d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka case Keyboard.CODE_LANGUAGE_SWITCH: 131581d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka handleLanguageSwitchKey(); 131681d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka break; 13174189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka default: 1318120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 131917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.isWordSeparator(primaryCode)) { 1320c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState); 13214189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } else { 1322ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok handleCharacter(primaryCode, x, y, spaceState); 13234189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 13244733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 132581d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka mShouldSwitchToLastSubtype = true; 13264733609947c0ec74e460bd714fffca0518ade93aJean Chalard break; 1327923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1328eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka switcher.onCodeInput(primaryCode); 1329dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Reset after any single keystroke 1330c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard if (!didAutoCorrect) 1331c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard mLastComposedWord.deactivate(); 1332dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = null; 1333923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1334a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 13355a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 13368aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onTextInput(CharSequence text) { 1337b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.commitVoiceInput(); 13389351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1339923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 1340923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 134166bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitTyped(ic, LastComposedWord.NOT_A_SEPARATOR); 1342fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard text = specificTldProcessingOnTextInput(ic, text); 1343fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (SPACE_STATE_PHANTOM == mSpaceState) { 13447a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka sendKeyCodePoint(Keyboard.CODE_SPACE); 1345fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 1346923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(text, 1); 1347923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1348b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 13498cab0b56eb8db311f158b18a361d9ceb85cff482Tadashi G. Takaoka mKeyboardSwitcher.onCodeInput(Keyboard.CODE_OUTPUT_TEXT); 1350120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 1351dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = text; 13522692a8700737d8eed268039aa27b22a31669da08Jean Chalard resetComposingState(true /* alsoResetLastComposedWord */); 1353923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1354923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1355fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // ic may not be null 1356fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard private CharSequence specificTldProcessingOnTextInput(final InputConnection ic, 1357fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard final CharSequence text) { 1358fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (text.length() <= 1 || text.charAt(0) != Keyboard.CODE_PERIOD 1359fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard || !Character.isLetter(text.charAt(1))) { 1360fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // Not a tld: do nothing. 1361fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard return text; 1362fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 136312d67e6d5d5bd764117038f3f666d4d7da0c10eaJean Chalard // We have a TLD (or something that looks like this): make sure we don't add 136412d67e6d5d5bd764117038f3f666d4d7da0c10eaJean Chalard // a space even if currently in phantom mode. 136512d67e6d5d5bd764117038f3f666d4d7da0c10eaJean Chalard mSpaceState = SPACE_STATE_NONE; 1366fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard final CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 1367fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (lastOne != null && lastOne.length() == 1 1368fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard && lastOne.charAt(0) == Keyboard.CODE_PERIOD) { 1369fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard return text.subSequence(1, text.length()); 1370fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } else { 1371fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard return text; 1372fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 1373fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 1374fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard 13755a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 13768aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCancelInput() { 137783e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka // User released a finger outside any key 13785f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka mKeyboardSwitcher.onCancelInput(); 137983e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka } 138083e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka 1381120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private void handleBackspace(final int spaceState) { 1382b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok if (mVoiceProxy.logAndRevertVoiceInput()) return; 1383504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1384504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (ic == null) return; 1385979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.beginBatchEdit(); 1386a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard handleBackspaceWhileInBatchEdit(spaceState, ic); 1387a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard ic.endBatchEdit(); 1388a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard } 1389979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1390a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard // "ic" may not be null. 1391a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard private void handleBackspaceWhileInBatchEdit(final int spaceState, final InputConnection ic) { 1392b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleBackspace(); 13934f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 13942245c3b5b3691928b08fd6accf8d4a21fb35e26bJean Chalard // In many cases, we may have to put the keyboard in auto-shift state again. 1395beb08b398fa73a26f2d42d6feec87e34a96ca2d9Tadashi G. Takaoka mHandler.postUpdateShiftState(); 13962245c3b5b3691928b08fd6accf8d4a21fb35e26bJean Chalard 13975c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { 13985c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // Cancel multi-character input: remove the text we just entered. 13995c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // This is triggered on backspace after a key that inputs multiple characters, 14005c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // like the smiley key or the .com key. 14015c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard ic.deleteSurroundingText(mEnteredText.length(), 0); 14025c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // If we have mEnteredText, then we know that mHasUncommittedTypedChars == false. 14035c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // In addition we know that spaceState is false, and that we should not be 14045c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // reverting any autocorrect at this point. So we can safely return. 14055c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard return; 14065c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard } 14075c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard 1408196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (mWordComposer.isComposingWord()) { 14093651220327c051d8017045aa5e8919461507b3f8Jean Chalard final int length = mWordComposer.size(); 1410923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (length > 0) { 14119318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.deleteLast(); 141277d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); 1413196d82cdd740580ed79d801483dbc282be85d076Jean Chalard // If we have deleted the last remaining character of a word, then we are not 1414196d82cdd740580ed79d801483dbc282be85d076Jean Chalard // isComposingWord() any more. 1415196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (!mWordComposer.isComposingWord()) { 1416196d82cdd740580ed79d801483dbc282be85d076Jean Chalard // Not composing word any more, so we can show bigrams. 1417cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.postUpdateBigramPredictions(); 141889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 1419196d82cdd740580ed79d801483dbc282be85d076Jean Chalard // Still composing a word, so we still have letters to deduce a suggestion from. 142089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.postUpdateSuggestions(); 142189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 1422923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1423923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(1, 0); 1424923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1425890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard } else { 14265935950d4431dd7eef18ebc370f2abeb614465d4Jean Chalard if (mLastComposedWord.canRevertCommit()) { 1427d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard Utils.Stats.onAutoCorrectionCancellation(); 14285935950d4431dd7eef18ebc370f2abeb614465d4Jean Chalard revertCommit(ic); 1429120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return; 1430120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1431d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard if (SPACE_STATE_DOUBLE == spaceState) { 14322124bc5bf5af31cf3d2789b70ebd2f24c815f5f4Jean Chalard if (revertDoubleSpaceWhileInBatchEdit(ic)) { 1433d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard // No need to reset mSpaceState, it has already be done (that's why we 1434d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard // receive it as a parameter) 1435d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard return; 1436d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard } 1437d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard } else if (SPACE_STATE_SWAP_PUNCTUATION == spaceState) { 1438d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard if (revertSwapPunctuation(ic)) { 1439d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard // Likewise 1440d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard return; 1441d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard } 14424733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 1443504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka 14444fef31510df542a3324426a6750950194d016086Jean Chalard // No cancelling of commit/double space/swap: we have a regular backspace. 14454fef31510df542a3324426a6750950194d016086Jean Chalard // We should backspace one char and restart suggestion if at the end of a word. 14464fef31510df542a3324426a6750950194d016086Jean Chalard if (mLastSelectionStart != mLastSelectionEnd) { 14474fef31510df542a3324426a6750950194d016086Jean Chalard // If there is a selection, remove it. 14484fef31510df542a3324426a6750950194d016086Jean Chalard final int lengthToDelete = mLastSelectionEnd - mLastSelectionStart; 14494fef31510df542a3324426a6750950194d016086Jean Chalard ic.setSelection(mLastSelectionEnd, mLastSelectionEnd); 14504fef31510df542a3324426a6750950194d016086Jean Chalard ic.deleteSurroundingText(lengthToDelete, 0); 14516558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } else { 14524fef31510df542a3324426a6750950194d016086Jean Chalard // There is no selection, just delete one character. 14534fef31510df542a3324426a6750950194d016086Jean Chalard if (NOT_A_CURSOR_POSITION == mLastSelectionEnd) { 14544fef31510df542a3324426a6750950194d016086Jean Chalard // This should never happen. 14554fef31510df542a3324426a6750950194d016086Jean Chalard Log.e(TAG, "Backspace when we don't know the selection position"); 14566558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 14574fef31510df542a3324426a6750950194d016086Jean Chalard ic.deleteSurroundingText(1, 0); 14584fef31510df542a3324426a6750950194d016086Jean Chalard if (mDeleteCount > DELETE_ACCELERATE_AT) { 14594fef31510df542a3324426a6750950194d016086Jean Chalard ic.deleteSurroundingText(1, 0); 1460edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard } 1461923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 14624fef31510df542a3324426a6750950194d016086Jean Chalard if (isSuggestionsRequested()) { 14634fef31510df542a3324426a6750950194d016086Jean Chalard restartSuggestionsOnWordBeforeCursorIfAtEndOfWord(ic); 14644fef31510df542a3324426a6750950194d016086Jean Chalard } 1465923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1466923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1467923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1468e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard // ic may be null 1469e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard private boolean maybeStripSpaceWhileInBatchEdit(final InputConnection ic, final int code, 1470e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard final int spaceState, final boolean isFromSuggestionStrip) { 1471e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard if (Keyboard.CODE_ENTER == code && SPACE_STATE_SWAP_PUNCTUATION == spaceState) { 1472e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard removeTrailingSpaceWhileInBatchEdit(ic); 1473e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard return false; 1474e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } else if ((SPACE_STATE_WEAK == spaceState 1475e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard || SPACE_STATE_SWAP_PUNCTUATION == spaceState) 1476e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard && isFromSuggestionStrip) { 1477b141c9cd3f6785bc0a4e1f5385f4e6e2e17955bbJean Chalard if (mSettingsValues.isWeakSpaceSwapper(code)) { 1478e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard return true; 1479e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } else { 1480b141c9cd3f6785bc0a4e1f5385f4e6e2e17955bbJean Chalard if (mSettingsValues.isWeakSpaceStripper(code)) { 1481e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard removeTrailingSpaceWhileInBatchEdit(ic); 1482e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 1483e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard return false; 1484e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 1485e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } else { 1486e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard return false; 1487e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 1488e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 1489e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard 1490ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok private void handleCharacter(final int primaryCode, final int x, 1491120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final int y, final int spaceState) { 1492b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleCharacter(); 1493b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard final InputConnection ic = getCurrentInputConnection(); 1494dafa7a8e15447544842975047f831883e67700c5Jean Chalard if (null != ic) ic.beginBatchEdit(); 1495dafa7a8e15447544842975047f831883e67700c5Jean Chalard // TODO: if ic is null, does it make any sense to call this? 1496ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok handleCharacterWhileInBatchEdit(primaryCode, x, y, spaceState, ic); 1497dafa7a8e15447544842975047f831883e67700c5Jean Chalard if (null != ic) ic.endBatchEdit(); 1498dafa7a8e15447544842975047f831883e67700c5Jean Chalard } 1499dafa7a8e15447544842975047f831883e67700c5Jean Chalard 1500dafa7a8e15447544842975047f831883e67700c5Jean Chalard // "ic" may be null without this crashing, but the behavior will be really strange 1501ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok private void handleCharacterWhileInBatchEdit(final int primaryCode, 1502dafa7a8e15447544842975047f831883e67700c5Jean Chalard final int x, final int y, final int spaceState, final InputConnection ic) { 1503196d82cdd740580ed79d801483dbc282be85d076Jean Chalard boolean isComposingWord = mWordComposer.isComposingWord(); 1504fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard 1505fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (SPACE_STATE_PHANTOM == spaceState && 1506fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard !mSettingsValues.isSymbolExcludedFromWordSeparators(primaryCode)) { 1507fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (isComposingWord) { 1508fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // Sanity check 1509fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard throw new RuntimeException("Should not be composing here"); 1510fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 15117a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka sendKeyCodePoint(Keyboard.CODE_SPACE); 1512fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 1513fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard 1514e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard if ((isAlphabet(primaryCode) 1515e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard || mSettingsValues.isSymbolExcludedFromWordSeparators(primaryCode)) 15163889462439357fd76c0b82dfd52e1ca6e0bafd2dKen Wakasa && isSuggestionsRequested() && !isCursorTouchingWord()) { 15177b5bc1ff4d4694045e69e6aff8a2b5365ff882d1Jean Chalard if (!isComposingWord) { 15186d1cbbc2ffb9d7046189174ec68b5b72bbc154b3Jean Chalard // Reset entirely the composing state anyway, then start composing a new word unless 15197b5bc1ff4d4694045e69e6aff8a2b5365ff882d1Jean Chalard // the character is a single quote. The idea here is, single quote is not a 15207b5bc1ff4d4694045e69e6aff8a2b5365ff882d1Jean Chalard // separator and it should be treated as a normal character, except in the first 15217b5bc1ff4d4694045e69e6aff8a2b5365ff882d1Jean Chalard // position where it should not start composing a word. 1522e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard isComposingWord = (Keyboard.CODE_SINGLE_QUOTE != primaryCode); 15232692a8700737d8eed268039aa27b22a31669da08Jean Chalard // Here we don't need to reset the last composed word. It will be reset 15242692a8700737d8eed268039aa27b22a31669da08Jean Chalard // when we commit this one, if we ever do; if on the other hand we backspace 15252692a8700737d8eed268039aa27b22a31669da08Jean Chalard // it entirely and resume suggestions on the previous word, we'd like to still 15262692a8700737d8eed268039aa27b22a31669da08Jean Chalard // have touch coordinates for it. 15272692a8700737d8eed268039aa27b22a31669da08Jean Chalard resetComposingState(false /* alsoResetLastComposedWord */); 1528611a5bdf650f7bc54bf40176f84f1cd9c87aa9aaJean Chalard clearSuggestions(); 1529923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1530923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 15317b5bc1ff4d4694045e69e6aff8a2b5365ff882d1Jean Chalard if (isComposingWord) { 1532ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok mWordComposer.add( 1533ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok primaryCode, x, y, mKeyboardSwitcher.getKeyboardView().getKeyDetector()); 1534923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 15351c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani // If it's the first letter, make note of auto-caps state 15369318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa if (mWordComposer.size() == 1) { 15379318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.setAutoCapitalized(getCurrentAutoCapsState()); 15381c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 153977d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); 1540923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1541d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1542923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1543e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard final boolean swapWeakSpace = maybeStripSpaceWhileInBatchEdit(ic, primaryCode, 1544e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard spaceState, KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x); 1545863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard 15467a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka sendKeyCodePoint(primaryCode); 1547e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard 1548e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard if (swapWeakSpace) { 1549e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard swapSwapperAndSpaceWhileInBatchEdit(ic); 1550e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard mSpaceState = SPACE_STATE_WEAK; 1551e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 15525262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // Some characters are not word separators, yet they don't start a new 15535262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // composing span. For these, we haven't changed the suggestion strip, and 15545262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // if the "add to dictionary" hint is shown, we should do so now. Examples of 15555262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // such characters include single quote, dollar, and others; the exact list is 15565262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // the list of characters for which we enter handleCharacterWhileInBatchEdit 15575262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // that don't match the test if ((isAlphabet...)) at the top of this method. 15585262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard if (null != mSuggestionsView && mSuggestionsView.dismissAddToDictionaryHint()) { 15595262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard mHandler.postUpdateBigramPredictions(); 15605262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard } 1561e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 1562e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard Utils.Stats.onNonSeparator((char)primaryCode, x, y); 1563923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1564923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1565c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard // Returns true if we did an autocorrection, false otherwise. 1566c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard private boolean handleSeparator(final int primaryCode, final int x, final int y, 1567120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final int spaceState) { 1568b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleSeparator(); 15694f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 157055b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // Should dismiss the "Touch again to save" message when handling separator 1571913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) { 1572cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.cancelUpdateBigramPredictions(); 1573d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 15746558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 15756558253160e2039c87f424bd814f402ecd31de3bKen Wakasa 1576c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard boolean didAutoCorrect = false; 1577923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Handle separator 15781b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1579923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1580923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 1581923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1582196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (mWordComposer.isComposingWord()) { 1583923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In certain languages where single quote is a separator, it's better 1584a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker // not to auto correct, but accept the typed word. For instance, 1585923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // in Italian dov' should not be expanded to dove' because the elision 1586923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // requires the last vowel to be removed. 1587f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled 1588dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard && !mInputAttributes.mInputTypeNoAutoCorrect; 158917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (shouldAutoCorrect && primaryCode != Keyboard.CODE_SINGLE_QUOTE) { 1590f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard commitCurrentAutoCorrection(primaryCode, ic); 1591c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard didAutoCorrect = true; 1592923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 159366bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitTyped(ic, primaryCode); 1594923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1595923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 15964ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1597e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard final boolean swapWeakSpace = maybeStripSpaceWhileInBatchEdit(ic, primaryCode, spaceState, 1598e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x); 1599863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard 160000ed3be95cee472685bcba1ea861ac75c61db690Jean Chalard if (SPACE_STATE_PHANTOM == spaceState && 160100ed3be95cee472685bcba1ea861ac75c61db690Jean Chalard mSettingsValues.isPhantomSpacePromotingSymbol(primaryCode)) { 160200ed3be95cee472685bcba1ea861ac75c61db690Jean Chalard sendKeyCodePoint(Keyboard.CODE_SPACE); 160300ed3be95cee472685bcba1ea861ac75c61db690Jean Chalard } 16047a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka sendKeyCodePoint(primaryCode); 160589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 160689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (Keyboard.CODE_SPACE == primaryCode) { 1607120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (isSuggestionsRequested()) { 1608120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (maybeDoubleSpaceWhileInBatchEdit(ic)) { 1609120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_DOUBLE; 1610120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } else if (!isShowingPunctuationList()) { 1611120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_WEAK; 1612120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1613126698fdd256a2e3734634d3b923cabd800064baJean Chalard } 1614120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 1615120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mHandler.startDoubleSpacesTimer(); 161689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (!isCursorTouchingWord()) { 161789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.cancelUpdateSuggestions(); 1618cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.postUpdateBigramPredictions(); 161989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 162089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 1621fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (swapWeakSpace) { 1622120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard swapSwapperAndSpaceWhileInBatchEdit(ic); 16234721427c7de3600f6fe7dfff16508a6a974fb3e4Jean Chalard mSpaceState = SPACE_STATE_SWAP_PUNCTUATION; 1624fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } else if (SPACE_STATE_PHANTOM == spaceState) { 1625fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // If we are in phantom space state, and the user presses a separator, we want to 1626fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // stay in phantom space state so that the next keypress has a chance to add the 1627fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // space. For example, if I type "Good dat", pick "day" from the suggestion strip 1628fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // then insert a comma and go on to typing the next word, I want the space to be 1629fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // inserted automatically before the next word, the same way it is when I don't 1630fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // input the comma. 1631fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard mSpaceState = SPACE_STATE_PHANTOM; 1632120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1633120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 163489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Set punctuation right away. onUpdateSelection will fire but tests whether it is 163589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // already displayed or not, so it's okay. 163655b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka setPunctuationSuggestions(); 1637923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1638120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 1639406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard Utils.Stats.onSeparator((char)primaryCode, x, y); 1640120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 1641923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1642923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1643923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1644c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard return didAutoCorrect; 1645923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1646466741d8a78965b8509bf527344f289e50873092Mike LeBeau 164777d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard private CharSequence getTextWithUnderline(final CharSequence text) { 16480a59ac2ba88ac1f99151d9336136bc6fe7d416c0Jean Chalard return mIsAutoCorrectionIndicatorOn 164977d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(this, text) 1650fda847a870829f1491cbd5325f9c985213081149Jean Chalard : text; 165177d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard } 165277d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard 1653923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleClose() { 165466bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitTyped(getCurrentInputConnection(), LastComposedWord.NOT_A_SEPARATOR); 1655b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleClose(); 1656923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project requestHideSelf(0); 1657c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 16581679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka if (inputView != null) 16591679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka inputView.closing(); 1660923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1661923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 16627a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isSuggestionsRequested() { 1663dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard return mInputAttributes.mIsSettingsSuggestionStripOn 1664c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka && (mCorrectionMode > 0 || isShowingSuggestionsStrip()); 1665923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1666a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 16677a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isShowingPunctuationList() { 1668cb8cb95d0afd340de9f1a0e15948f0068d2450bcKen Wakasa if (mSuggestionsView == null) return false; 1669913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka return mSettingsValues.mSuggestPuncList == mSuggestionsView.getSuggestions(); 16707599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 16717599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 16727a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isShowingSuggestionsStrip() { 16737599cfea4a2d56f4779452ec8e8742f7b9629cc0satok return (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_VALUE) 16747599cfea4a2d56f4779452ec8e8742f7b9629cc0satok || (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 167538f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka && mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT); 16767599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 16777599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 1678913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka public boolean isSuggestionsStripVisible() { 1679913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView == null) 1680b5e00d5841b946de8970875231456228ae0eb6b1Ken Wakasa return false; 1681d0c5f9395a1b94e8425982e353d090f972dc44f0Jean Chalard if (mSuggestionsView.isShowingAddToDictionaryHint()) 16829fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 16839fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!isShowingSuggestionsStrip()) 16849fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return false; 1685dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard if (mInputAttributes.mApplicationSpecifiedCompletionOn) 16869fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 16879fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return isSuggestionsRequested(); 1688923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1689923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1690409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void switchToKeyboardView() { 1691060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (DEBUG) { 1692060efb6d82af1f896d90cb845c8ae07c726f85e1satok Log.d(TAG, "Switch to keyboard view."); 1693060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 1694c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka View v = mKeyboardSwitcher.getKeyboardView(); 1695060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (v != null) { 1696060efb6d82af1f896d90cb845c8ae07c726f85e1satok // Confirms that the keyboard view doesn't have parent view. 1697060efb6d82af1f896d90cb845c8ae07c726f85e1satok ViewParent p = v.getParent(); 1698060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (p != null && p instanceof ViewGroup) { 1699060efb6d82af1f896d90cb845c8ae07c726f85e1satok ((ViewGroup) p).removeView(v); 17005a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } 1701060efb6d82af1f896d90cb845c8ae07c726f85e1satok setInputView(v); 1702060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 1703913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShown(isSuggestionsStripVisible()); 1704060efb6d82af1f896d90cb845c8ae07c726f85e1satok updateInputViewShown(); 1705060efb6d82af1f896d90cb845c8ae07c726f85e1satok mHandler.postUpdateSuggestions(); 1706466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1707466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1708409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void clearSuggestions() { 1709dd931c47be1a4fe4cf86c8ad018e479c2cbdf8ceJean Chalard setSuggestions(SuggestedWords.EMPTY, false); 17107204eab3da916d8873b7eeee4b4528a6b82de19cJean Chalard setAutoCorrectionIndicator(false); 1711466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1712466741d8a78965b8509bf527344f289e50873092Mike LeBeau 17132be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard private void setSuggestions(final SuggestedWords words, final boolean isAutoCorrection) { 1714913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) { 1715913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.setSuggestions(words); 1716dd931c47be1a4fe4cf86c8ad018e479c2cbdf8ceJean Chalard mKeyboardSwitcher.onAutoCorrectionStateChanged(isAutoCorrection); 1717466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1718d02783cb63293507e8544ea60d07559092ce83d4Jean Chalard } 1719ec780e2868962bf17f0dfd35d36895f543bde40asatok 172038e535e59676ac4d7bf27026fe3e16fcd9eb292eJean Chalard private void setAutoCorrectionIndicator(final boolean newAutoCorrectionIndicator) { 1721ec780e2868962bf17f0dfd35d36895f543bde40asatok // Put a blue underline to a word in TextView which will be auto-corrected. 1722ec780e2868962bf17f0dfd35d36895f543bde40asatok final InputConnection ic = getCurrentInputConnection(); 17232be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard if (ic == null) return; 17242be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard if (mIsAutoCorrectionIndicatorOn != newAutoCorrectionIndicator 17252be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard && mWordComposer.isComposingWord()) { 17262be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard mIsAutoCorrectionIndicatorOn = newAutoCorrectionIndicator; 17272be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard final CharSequence textWithUnderline = 17282be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard getTextWithUnderline(mWordComposer.getTypedWord()); 17292be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard ic.setComposingText(textWithUnderline, 1); 1730ec780e2868962bf17f0dfd35d36895f543bde40asatok } 1731466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1732466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1733409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void updateSuggestions() { 1734923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Check if we have a suggestion engine attached. 17359fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if ((mSuggest == null || !isSuggestionsRequested()) 1736b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok && !mVoiceProxy.isVoiceInputHighlighted()) { 1737edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard if (mWordComposer.isComposingWord()) { 1738edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard Log.w(TAG, "Called updateSuggestions but suggestions were not requested!"); 1739edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard mWordComposer.setAutoCorrection(mWordComposer.getTypedWord()); 1740edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard } 1741923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1742923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1743466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1744cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard mHandler.cancelUpdateSuggestions(); 1745cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard mHandler.cancelUpdateBigramPredictions(); 1746cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard 1747196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (!mWordComposer.isComposingWord()) { 1748ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setPunctuationSuggestions(); 1749923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1750923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1751979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 17529f67e12a0e3f77985fb8bafe0db4c00e32317b9asatok // TODO: May need a better way of retrieving previous word 175340f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final InputConnection ic = getCurrentInputConnection(); 175440f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final CharSequence prevWord; 175540f7efc172928bdd6048e91421a766abe5b22996Jean Chalard if (null == ic) { 175640f7efc172928bdd6048e91421a766abe5b22996Jean Chalard prevWord = null; 175740f7efc172928bdd6048e91421a766abe5b22996Jean Chalard } else { 175840f7efc172928bdd6048e91421a766abe5b22996Jean Chalard prevWord = EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators); 175940f7efc172928bdd6048e91421a766abe5b22996Jean Chalard } 1760dc5dfe37e06eb1d550d7aa5156cff226334d4e1eJean Chalard 1761dc5dfe37e06eb1d550d7aa5156cff226334d4e1eJean Chalard final CharSequence typedWord = mWordComposer.getTypedWord(); 17622be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard // getSuggestedWords handles gracefully a null value of prevWord 17635b0643f50d8c363296360f3ceaf32f7edc157141Jean Chalard final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer, 17643708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(), mCorrectionMode); 1765923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1766a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // Basically, we update the suggestion strip only when suggestion count > 1. However, 1767a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // there is an exception: We update the suggestion strip whenever typed word's length 1768f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // is 1 or typed word is found in dictionary, regardless of suggestion count. Actually, 1769f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // in most cases, suggestion count is 1 when typed word's length is 1, but we do always 1770f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // need to clear the previous state when the user starts typing a word (i.e. typed word's 1771f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // length == 1). 17725b0643f50d8c363296360f3ceaf32f7edc157141Jean Chalard if (suggestedWords.size() > 1 || typedWord.length() == 1 17735b0643f50d8c363296360f3ceaf32f7edc157141Jean Chalard || !suggestedWords.mAllowsToBeAutoCorrected 1774838629aea00ce90231df97f1dae3d8273ba80cbdJean Chalard || mSuggestionsView.isShowingAddToDictionaryHint()) { 17755b0643f50d8c363296360f3ceaf32f7edc157141Jean Chalard showSuggestions(suggestedWords, typedWord); 1776838629aea00ce90231df97f1dae3d8273ba80cbdJean Chalard } else { 1777838629aea00ce90231df97f1dae3d8273ba80cbdJean Chalard SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions(); 1778838629aea00ce90231df97f1dae3d8273ba80cbdJean Chalard if (previousSuggestions == mSettingsValues.mSuggestPuncList) { 1779838629aea00ce90231df97f1dae3d8273ba80cbdJean Chalard previousSuggestions = SuggestedWords.EMPTY; 1780fe1a6d961cf039357f061482461e4d2e951ad346satok } 17814ee186920e642ae8ebe0b6c97dfdceb0ad2fdeefJean Chalard final ArrayList<SuggestedWords.SuggestedWordInfo> typedWordAndPreviousSuggestions = 178288bf1ba5263f5a5c1df367ddc401db4109ef8677Jean Chalard SuggestedWords.getTypedWordAndPreviousSuggestions( 17834ee186920e642ae8ebe0b6c97dfdceb0ad2fdeefJean Chalard typedWord, previousSuggestions); 17847d55c891afdf7e74e505acac998a95a9ca7a9ec2Jean Chalard final SuggestedWords obsoleteSuggestedWords = 1785bdf6d1b18b3cebdde5f39d10066ead34be161bafJean Chalard new SuggestedWords(typedWordAndPreviousSuggestions, 17862e2519ee914d4bf9462950553840557a4c19faedJean Chalard false /* typedWordValid */, 1787bdf6d1b18b3cebdde5f39d10066ead34be161bafJean Chalard false /* hasAutoCorrectionCandidate */, 1788b5eeb724fc98bb7169683539027d9ba54ffb8b14Jean Chalard false /* allowsToBeAutoCorrected */, 178903a35170751a635332c00bf6c272a0127a255cf6Jean Chalard false /* isPunctuationSuggestions */, 179003a35170751a635332c00bf6c272a0127a255cf6Jean Chalard true /* isObsoleteSuggestions */); 17917d55c891afdf7e74e505acac998a95a9ca7a9ec2Jean Chalard showSuggestions(obsoleteSuggestedWords, typedWord); 17929fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka } 1793979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 17944a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani 1795d992fa847da8f232d961ff097857757bfbff73a5Jean Chalard public void showSuggestions(final SuggestedWords suggestedWords, final CharSequence typedWord) { 1796d992fa847da8f232d961ff097857757bfbff73a5Jean Chalard final CharSequence autoCorrection; 17977e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka if (suggestedWords.size() > 0) { 179868823ae08e820f0951447ed12c1bd32a24333d2eJean Chalard if (suggestedWords.hasAutoCorrectionWord()) { 1799d992fa847da8f232d961ff097857757bfbff73a5Jean Chalard autoCorrection = suggestedWords.getWord(1); 1800923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1801d992fa847da8f232d961ff097857757bfbff73a5Jean Chalard autoCorrection = typedWord; 1802923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1803923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1804d992fa847da8f232d961ff097857757bfbff73a5Jean Chalard autoCorrection = null; 1805923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1806d992fa847da8f232d961ff097857757bfbff73a5Jean Chalard mWordComposer.setAutoCorrection(autoCorrection); 18079b01890254c62a30b079bd9f79a30f9541faf11bJean Chalard final boolean isAutoCorrection = suggestedWords.willAutoCorrect(); 1808dd931c47be1a4fe4cf86c8ad018e479c2cbdf8ceJean Chalard setSuggestions(suggestedWords, isAutoCorrection); 1809dd931c47be1a4fe4cf86c8ad018e479c2cbdf8ceJean Chalard setAutoCorrectionIndicator(isAutoCorrection); 1810913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShown(isSuggestionsStripVisible()); 1811923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1812923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1813f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard private void commitCurrentAutoCorrection(final int separatorCodePoint, 1814f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard final InputConnection ic) { 1815913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka // Complete any pending suggestions query first 1816d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka if (mHandler.hasPendingUpdateSuggestions()) { 1817d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 1818923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 1819923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1820117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard final CharSequence autoCorrection = mWordComposer.getAutoCorrectionOrNull(); 1821117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard if (autoCorrection != null) { 1822117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard final String typedWord = mWordComposer.getTypedWord(); 182346798d8f1f3d9012433d000790ba30ba910c0fa0Jean Chalard if (TextUtils.isEmpty(typedWord)) { 182446798d8f1f3d9012433d000790ba30ba910c0fa0Jean Chalard throw new RuntimeException("We have an auto-correction but the typed word " 182546798d8f1f3d9012433d000790ba30ba910c0fa0Jean Chalard + "is empty? Impossible! I must commit suicide."); 182646798d8f1f3d9012433d000790ba30ba910c0fa0Jean Chalard } 1827f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard Utils.Stats.onAutoCorrection(typedWord, autoCorrection.toString(), separatorCodePoint); 18284733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 182966bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitChosenWord(autoCorrection, LastComposedWord.COMMIT_TYPE_DECIDED_WORD, 183066bb563535dbe3672f99f75bd71763a551444867Jean Chalard separatorCodePoint); 1831c24f66e18007b5aba32bfab8f86eb7f03fa6c1b7Jean Chalard // Add the word to the user history dictionary 1832c24f66e18007b5aba32bfab8f86eb7f03fa6c1b7Jean Chalard addToUserHistoryDictionary(autoCorrection); 1833f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard if (!typedWord.equals(autoCorrection) && null != ic) { 18341c6cf26c3705e845418a29718c034598b52293ccJean Chalard // This will make the correction flash for a short while as a visual clue 18351c6cf26c3705e845418a29718c034598b52293ccJean Chalard // to the user that auto-correction happened. 18361c6cf26c3705e845418a29718c034598b52293ccJean Chalard InputConnectionCompatUtils.commitCorrection(ic, 18371c6cf26c3705e845418a29718c034598b52293ccJean Chalard mLastSelectionEnd - typedWord.length(), typedWord, autoCorrection); 18381c6cf26c3705e845418a29718c034598b52293ccJean Chalard } 1839923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1840923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1841923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1842c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka @Override 18432e2d6b4d4060ed3b956b4bd4c1f89b5d9c87b525Jean Chalard public void pickSuggestionManually(final int index, final CharSequence suggestion) { 18448cc8f26adfe0f06cebc697dac43a856326cf7afcTadashi G. Takaoka final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions(); 184517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mVoiceProxy.flushAndLogAllTextModificationCounters(index, suggestion, 184617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mWordSeparators); 18474f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1848845b24d9d31072b98958c557366617ad1c34f1b7Jean Chalard if (SPACE_STATE_PHANTOM == mSpaceState && suggestion.length() > 0) { 1849845b24d9d31072b98958c557366617ad1c34f1b7Jean Chalard int firstChar = Character.codePointAt(suggestion, 0); 1850845b24d9d31072b98958c557366617ad1c34f1b7Jean Chalard if ((!mSettingsValues.isWeakSpaceStripper(firstChar)) 1851845b24d9d31072b98958c557366617ad1c34f1b7Jean Chalard && (!mSettingsValues.isWeakSpaceSwapper(firstChar))) { 1852845b24d9d31072b98958c557366617ad1c34f1b7Jean Chalard sendKeyCodePoint(Keyboard.CODE_SPACE); 1853845b24d9d31072b98958c557366617ad1c34f1b7Jean Chalard } 1854845b24d9d31072b98958c557366617ad1c34f1b7Jean Chalard } 1855845b24d9d31072b98958c557366617ad1c34f1b7Jean Chalard 1856dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard if (mInputAttributes.mApplicationSpecifiedCompletionOn 1857dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard && mApplicationSpecifiedCompletions != null 18581b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka && index >= 0 && index < mApplicationSpecifiedCompletions.length) { 1859913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) { 1860913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.clear(); 1861923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1862b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1863611a5bdf650f7bc54bf40176f84f1cd9c87aa9aaJean Chalard resetComposingState(true /* alsoResetLastComposedWord */); 1864e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard final InputConnection ic = getCurrentInputConnection(); 18659a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 1866e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index]; 1867e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard ic.commitCompletion(completionInfo); 18689a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1869923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1870923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 18716a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 1872e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard // If this is a punctuation picked from the suggestion strip, pass it to onCodeInput 1873e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard if (suggestion.length() == 1 && isShowingPunctuationList()) { 1874979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Word separators are suggested before the user inputs something. 1875979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // So, LatinImeLogger logs "" as a user's input. 18768cc8f26adfe0f06cebc697dac43a856326cf7afcTadashi G. Takaoka LatinImeLogger.logOnManualSuggestion("", suggestion.toString(), index, suggestedWords); 1877e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard // Rely on onCodeInput to do the complicated swapping/stripping logic consistently. 18782e2d6b4d4060ed3b956b4bd4c1f89b5d9c87b525Jean Chalard final int primaryCode = suggestion.charAt(0); 1879ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok onCodeInput(primaryCode, 1880e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard KeyboardActionListener.SUGGESTION_STRIP_COORDINATE, 1881e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard KeyboardActionListener.SUGGESTION_STRIP_COORDINATE); 18826a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani return; 18836a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 1884af9fe5c5fcad1db22f605e0568c9a77cef178d22Jean Chalard // We need to log before we commit, because the word composer will store away the user 1885af9fe5c5fcad1db22f605e0568c9a77cef178d22Jean Chalard // typed word. 1886af9fe5c5fcad1db22f605e0568c9a77cef178d22Jean Chalard LatinImeLogger.logOnManualSuggestion(mWordComposer.getTypedWord().toString(), 18878cc8f26adfe0f06cebc697dac43a856326cf7afcTadashi G. Takaoka suggestion.toString(), index, suggestedWords); 18884733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 188966bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitChosenWord(suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK, 189066bb563535dbe3672f99f75bd71763a551444867Jean Chalard LastComposedWord.NOT_A_SEPARATOR); 1891c24f66e18007b5aba32bfab8f86eb7f03fa6c1b7Jean Chalard // Add the word to the user history dictionary 1892c24f66e18007b5aba32bfab8f86eb7f03fa6c1b7Jean Chalard addToUserHistoryDictionary(suggestion); 1893fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard mSpaceState = SPACE_STATE_PHANTOM; 1894fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // TODO: is this necessary? 1895fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard mKeyboardSwitcher.updateShiftState(); 1896979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1897c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // We should show the "Touch again to save" hint if the user pressed the first entry 1898c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // AND either: 18997f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is no dictionary (we know that because we tried to load it => null != mSuggest 1900c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // AND mSuggest.hasMainDictionary() is false) 19017f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is a dictionary and the word is not in it 19027f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // Please note that if mSuggest is null, it means that everything is off: suggestion 19037f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // and correction, so we shouldn't try to show the hint 19047f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // We used to look at mCorrectionMode here, but showing the hint should have nothing 19057f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // to do with the autocorrection setting. 1906bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean showingAddToDictionaryHint = index == 0 && mSuggest != null 1907bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // If there is no dictionary the hint should be shown. 1908c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa && (!mSuggest.hasMainDictionary() 1909bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // If "suggestion" is not in the dictionary, the hint should be shown. 1910bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok || !AutoCorrection.isValidWord( 1911bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok mSuggest.getUnigramDictionaries(), suggestion, true)); 1912b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani 1913406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard Utils.Stats.onSeparator((char)Keyboard.CODE_SPACE, WordComposer.NOT_A_COORDINATE, 1914406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard WordComposer.NOT_A_COORDINATE); 1915777118a40a363ccab69a00016d3156066513cb78Jean Chalard if (!showingAddToDictionaryHint) { 1916364da8c618303a7764595d2c15ee034a7671365dKen Wakasa // If we're not showing the "Touch again to save", then show corrections again. 1917979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // In case the cursor position doesn't change, make sure we show the suggestions again. 191841ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard updateBigramPredictions(); 191941ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // Updating the predictions right away may be slow and feel unresponsive on slower 192041ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // terminals. On the other hand if we just postUpdateBigramPredictions() it will 192141ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // take a noticeable delay to update them which may feel uneasy. 192295a6e58ebcd8f44b970a8238cf30e48b10fc4b61Jean Chalard } else { 192388562bec54658840dcce352127bdc15705c20a89Jean Chalard if (mIsUserDictionaryAvailable) { 1924644d33d60ea5a87501274488013d65f55238895eKen Wakasa mSuggestionsView.showAddToDictionaryHint( 1925644d33d60ea5a87501274488013d65f55238895eKen Wakasa suggestion, mSettingsValues.mHintToSaveText); 1926ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka } else { 1927ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1928ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka } 192966a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani } 1930923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1931a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1932979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 19338558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa * Commits the chosen word to the text field and saves it for later retrieval. 1934979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 193566bb563535dbe3672f99f75bd71763a551444867Jean Chalard private void commitChosenWord(final CharSequence bestWord, final int commitType, 193666bb563535dbe3672f99f75bd71763a551444867Jean Chalard final int separatorCode) { 19379351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1938923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 19391fef530ec7626fa16777f52b48191e61db8f46d4satok mVoiceProxy.rememberReplacedWord(bestWord, mSettingsValues.mWordSeparators); 19401531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard if (mSettingsValues.mEnableSuggestionSpanInsertion) { 19411531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions(); 19421531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan( 19431531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard this, bestWord, suggestedWords), 1); 19441531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard } else { 19451531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard ic.commitText(bestWord, 1); 19461531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard } 1947923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 19480fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard // TODO: figure out here if this is an auto-correct or if the best word is actually 19490fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard // what user typed. Note: currently this is done much later in 1950bdf89ce5feedb03e67b43f530b1eb9bd44203c63Jean Chalard // LastComposedWord#didCommitTypedWord by string equality of the remembered 19510fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard // strings. 195266bb563535dbe3672f99f75bd71763a551444867Jean Chalard mLastComposedWord = mWordComposer.commitWord(commitType, bestWord.toString(), 195366bb563535dbe3672f99f75bd71763a551444867Jean Chalard separatorCode); 1954923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1955923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 195641ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard public void updateBigramPredictions() { 195789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (mSuggest == null || !isSuggestionsRequested()) 195889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard return; 195989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 196017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (!mSettingsValues.mBigramPredictionEnabled) { 1961cb3320179d39a7983874697a0aa428b127675c9dJean Chalard setPunctuationSuggestions(); 1962cb3320179d39a7983874697a0aa428b127675c9dJean Chalard return; 1963cb3320179d39a7983874697a0aa428b127675c9dJean Chalard } 1964cb3320179d39a7983874697a0aa428b127675c9dJean Chalard 19658e19b1183e4925b7c396de45a5e4e7d67a7b876aJean Chalard final SuggestedWords suggestedWords; 1966a333ff19ef330c93287cfa0f6568d0cdcd431b04Jean Chalard if (mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { 1967a333ff19ef330c93287cfa0f6568d0cdcd431b04Jean Chalard final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(), 1968a333ff19ef330c93287cfa0f6568d0cdcd431b04Jean Chalard mSettingsValues.mWordSeparators); 19690cf422fbb763e2672fb2f9e8e1e8af91d2e87cb3Jean Chalard if (!TextUtils.isEmpty(prevWord)) { 19705b0643f50d8c363296360f3ceaf32f7edc157141Jean Chalard suggestedWords = mSuggest.getBigramPredictions(prevWord); 19710cf422fbb763e2672fb2f9e8e1e8af91d2e87cb3Jean Chalard } else { 19728e19b1183e4925b7c396de45a5e4e7d67a7b876aJean Chalard suggestedWords = null; 19730cf422fbb763e2672fb2f9e8e1e8af91d2e87cb3Jean Chalard } 1974a333ff19ef330c93287cfa0f6568d0cdcd431b04Jean Chalard } else { 19758e19b1183e4925b7c396de45a5e4e7d67a7b876aJean Chalard suggestedWords = null; 1976a333ff19ef330c93287cfa0f6568d0cdcd431b04Jean Chalard } 197789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 19788e19b1183e4925b7c396de45a5e4e7d67a7b876aJean Chalard if (null != suggestedWords && suggestedWords.size() > 0) { 197989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Explicitly supply an empty typed word (the no-second-arg version of 198089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // showSuggestions will retrieve the word near the cursor, we don't want that here) 19818e19b1183e4925b7c396de45a5e4e7d67a7b876aJean Chalard showSuggestions(suggestedWords, ""); 198289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 198389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (!isShowingPunctuationList()) setPunctuationSuggestions(); 198489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 198589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 198689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 19877a8dac55278cedd838be325f56b4c52d973c61f5satok public void setPunctuationSuggestions() { 1988dd931c47be1a4fe4cf86c8ad018e479c2cbdf8ceJean Chalard setSuggestions(mSettingsValues.mSuggestPuncList, false); 19897204eab3da916d8873b7eeee4b4528a6b82de19cJean Chalard setAutoCorrectionIndicator(false); 1990913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShown(isSuggestionsStripVisible()); 19916a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 19926a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 1993979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 1994f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard * Adds to the UserBigramDictionary and/or UserUnigramDictionary 1995979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 1996c24f66e18007b5aba32bfab8f86eb7f03fa6c1b7Jean Chalard private void addToUserHistoryDictionary(final CharSequence suggestion) { 1997979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (suggestion == null || suggestion.length() < 1) return; 1998bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok 19990c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be 20000c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // adding words in situations where the user or application really didn't 20010c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // want corrections enabled or learned. 2002979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (!(mCorrectionMode == Suggest.CORRECTION_FULL 2003979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) { 2004979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return; 2005979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2006bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok 2007e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mUserBigramDictionary != null) { 2008c68d1bbfafe4b2041db49523c044123f78d6635dJean Chalard mUserBigramDictionary.addUnigram(suggestion.toString()); 200940f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final InputConnection ic = getCurrentInputConnection(); 201040f7efc172928bdd6048e91421a766abe5b22996Jean Chalard if (null != ic) { 201140f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final CharSequence prevWord = 201240f7efc172928bdd6048e91421a766abe5b22996Jean Chalard EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators); 2013c24f66e18007b5aba32bfab8f86eb7f03fa6c1b7Jean Chalard if (null != prevWord) { 2014c24f66e18007b5aba32bfab8f86eb7f03fa6c1b7Jean Chalard mUserBigramDictionary.addBigramPair(prevWord.toString(), suggestion.toString()); 201540f7efc172928bdd6048e91421a766abe5b22996Jean Chalard } 2016979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 201732e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 201832e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 201932e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani 20207a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isCursorTouchingWord() { 20219351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 2022923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return false; 20238667bbeab3321e05f518770f7360a3fef52b4407Jean Chalard CharSequence before = ic.getTextBeforeCursor(1, 0); 20248667bbeab3321e05f518770f7360a3fef52b4407Jean Chalard CharSequence after = ic.getTextAfterCursor(1, 0); 20256ec1209a33fe2dc151b86d3f662e22e564e2f4f8Jean Chalard if (!TextUtils.isEmpty(before) && !mSettingsValues.isWordSeparator(before.charAt(0)) 20266ec1209a33fe2dc151b86d3f662e22e564e2f4f8Jean Chalard && !mSettingsValues.isSymbolExcludedFromWordSeparators(before.charAt(0))) { 2027923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 2028923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 20296ec1209a33fe2dc151b86d3f662e22e564e2f4f8Jean Chalard if (!TextUtils.isEmpty(after) && !mSettingsValues.isWordSeparator(after.charAt(0)) 20306ec1209a33fe2dc151b86d3f662e22e564e2f4f8Jean Chalard && !mSettingsValues.isSymbolExcludedFromWordSeparators(after.charAt(0))) { 2031923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 2032923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2033923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 2034923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2035a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2036120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // "ic" must not be null 20378ff0564f6a7c78e2fda517ea49b2ac2fa96d0f8eJean Chalard private static boolean sameAsTextBeforeCursor(final InputConnection ic, 20388ff0564f6a7c78e2fda517ea49b2ac2fa96d0f8eJean Chalard final CharSequence text) { 20398ff0564f6a7c78e2fda517ea49b2ac2fa96d0f8eJean Chalard final CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0); 2040dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani return TextUtils.equals(text, beforeText); 2041dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani } 2042dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 2043120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // "ic" must not be null 20446b1f500da451de56932a8b2a99c63857994ece85Jean Chalard /** 20456b1f500da451de56932a8b2a99c63857994ece85Jean Chalard * Check if the cursor is actually at the end of a word. If so, restart suggestions on this 20466b1f500da451de56932a8b2a99c63857994ece85Jean Chalard * word, else do nothing. 20476b1f500da451de56932a8b2a99c63857994ece85Jean Chalard */ 20486b1f500da451de56932a8b2a99c63857994ece85Jean Chalard private void restartSuggestionsOnWordBeforeCursorIfAtEndOfWord( 20496b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final InputConnection ic) { 20506b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Bail out if the cursor is not at the end of a word (cursor must be preceded by 20516b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // non-whitespace, non-separator, non-start-of-text) 20526b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Example ("|" is the cursor here) : <SOL>"|a" " |a" " | " all get rejected here. 20536b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final CharSequence textBeforeCursor = ic.getTextBeforeCursor(1, 0); 20546b1f500da451de56932a8b2a99c63857994ece85Jean Chalard if (TextUtils.isEmpty(textBeforeCursor) 20556b1f500da451de56932a8b2a99c63857994ece85Jean Chalard || mSettingsValues.isWordSeparator(textBeforeCursor.charAt(0))) return; 20566b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 20576b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Bail out if the cursor is in the middle of a word (cursor must be followed by whitespace, 20586b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // separator or end of line/text) 20596b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Example: "test|"<EOL> "te|st" get rejected here 20606b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final CharSequence textAfterCursor = ic.getTextAfterCursor(1, 0); 20616b1f500da451de56932a8b2a99c63857994ece85Jean Chalard if (!TextUtils.isEmpty(textAfterCursor) 20626b1f500da451de56932a8b2a99c63857994ece85Jean Chalard && !mSettingsValues.isWordSeparator(textAfterCursor.charAt(0))) return; 20636b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 20646b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Bail out if word before cursor is 0-length or a single non letter (like an apostrophe) 2065fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // Example: " -|" gets rejected here but "e-|" and "e|" are okay 2066fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard CharSequence word = EditingUtils.getWordAtCursor(ic, mSettingsValues.mWordSeparators); 2067fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // We don't suggest on leading single quotes, so we have to remove them from the word if 2068fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // it starts with single quotes. 2069fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard while (!TextUtils.isEmpty(word) && Keyboard.CODE_SINGLE_QUOTE == word.charAt(0)) { 2070fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard word = word.subSequence(1, word.length()); 2071fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard } 20726b1f500da451de56932a8b2a99c63857994ece85Jean Chalard if (TextUtils.isEmpty(word)) return; 2073fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard final char firstChar = word.charAt(0); // we just tested that word is not empty 2074fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard if (word.length() == 1 && !Character.isLetter(firstChar)) return; 2075fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard 2076fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // We only suggest on words that start with a letter or a symbol that is excluded from 2077fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // word separators (see #handleCharacterWhileInBatchEdit). 2078fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard if (!(isAlphabet(firstChar) 2079fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard || mSettingsValues.isSymbolExcludedFromWordSeparators(firstChar))) { 2080fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard return; 2081fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard } 20826b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 20836b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Okay, we are at the end of a word. Restart suggestions. 20846b1f500da451de56932a8b2a99c63857994ece85Jean Chalard restartSuggestionsOnWordBeforeCursor(ic, word); 20856b1f500da451de56932a8b2a99c63857994ece85Jean Chalard } 20866b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 20876b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // "ic" must not be null 20886b1f500da451de56932a8b2a99c63857994ece85Jean Chalard private void restartSuggestionsOnWordBeforeCursor(final InputConnection ic, 20896b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final CharSequence word) { 20903708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka mWordComposer.setComposingWord(word, mKeyboardSwitcher.getKeyboard()); 20916b1f500da451de56932a8b2a99c63857994ece85Jean Chalard ic.deleteSurroundingText(word.length(), 0); 20926b1f500da451de56932a8b2a99c63857994ece85Jean Chalard ic.setComposingText(word, 1); 20936b1f500da451de56932a8b2a99c63857994ece85Jean Chalard mHandler.postUpdateSuggestions(); 20946b1f500da451de56932a8b2a99c63857994ece85Jean Chalard } 20956b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 20966b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // "ic" must not be null 20975935950d4431dd7eef18ebc370f2abeb614465d4Jean Chalard private void revertCommit(final InputConnection ic) { 2098b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard final String originallyTypedWord = mLastComposedWord.mTypedWord; 2099cf9d92629cae88273805eaf7984fcfdd8afd11f5Jean Chalard final CharSequence committedWord = mLastComposedWord.mCommittedWord; 2100cf9d92629cae88273805eaf7984fcfdd8afd11f5Jean Chalard final int cancelLength = committedWord.length(); 2101ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok final int separatorLength = LastComposedWord.getSeparatorLength( 2102193d23f40e1556074f323b7bd9695759f4798efeJean Chalard mLastComposedWord.mSeparatorCode); 2103193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // TODO: should we check our saved separator against the actual contents of the text view? 2104890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard if (DEBUG) { 2105b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard if (mWordComposer.isComposingWord()) { 21065935950d4431dd7eef18ebc370f2abeb614465d4Jean Chalard throw new RuntimeException("revertCommit, but we are composing a word"); 2107b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard } 2108890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard final String wordBeforeCursor = 2109193d23f40e1556074f323b7bd9695759f4798efeJean Chalard ic.getTextBeforeCursor(cancelLength + separatorLength, 0) 2110193d23f40e1556074f323b7bd9695759f4798efeJean Chalard .subSequence(0, cancelLength).toString(); 2111cf9d92629cae88273805eaf7984fcfdd8afd11f5Jean Chalard if (!TextUtils.equals(committedWord, wordBeforeCursor)) { 21125935950d4431dd7eef18ebc370f2abeb614465d4Jean Chalard throw new RuntimeException("revertCommit check failed: we thought we were " 2113cf9d92629cae88273805eaf7984fcfdd8afd11f5Jean Chalard + "reverting \"" + committedWord 2114890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard + "\", but before the cursor we found \"" + wordBeforeCursor + "\""); 2115890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard } 21168558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa } 2117193d23f40e1556074f323b7bd9695759f4798efeJean Chalard ic.deleteSurroundingText(cancelLength + separatorLength, 0); 2118193d23f40e1556074f323b7bd9695759f4798efeJean Chalard if (0 == separatorLength || mLastComposedWord.didCommitTypedWord()) { 2119193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // This is the case when we cancel a manual pick. 2120193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // We should restart suggestion on the word right away. 212132f0af1fc48f67907f0e731e18359f29e2b1df14Jean Chalard mWordComposer.resumeSuggestionOnLastComposedWord(mLastComposedWord); 212232f0af1fc48f67907f0e731e18359f29e2b1df14Jean Chalard ic.setComposingText(originallyTypedWord, 1); 2123193d23f40e1556074f323b7bd9695759f4798efeJean Chalard } else { 2124193d23f40e1556074f323b7bd9695759f4798efeJean Chalard ic.commitText(originallyTypedWord, 1); 2125193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // Re-insert the separator 2126193d23f40e1556074f323b7bd9695759f4798efeJean Chalard sendKeyCodePoint(mLastComposedWord.mSeparatorCode); 2127193d23f40e1556074f323b7bd9695759f4798efeJean Chalard Utils.Stats.onSeparator(mLastComposedWord.mSeparatorCode, WordComposer.NOT_A_COORDINATE, 2128193d23f40e1556074f323b7bd9695759f4798efeJean Chalard WordComposer.NOT_A_COORDINATE); 2129193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // Don't restart suggestion yet. We'll restart if the user deletes the 2130193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // separator. 2131193d23f40e1556074f323b7bd9695759f4798efeJean Chalard } 2132b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; 2133890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard mHandler.cancelUpdateBigramPredictions(); 2134890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard mHandler.postUpdateSuggestions(); 2135890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard } 2136890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard 2137890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard // "ic" must not be null 21382124bc5bf5af31cf3d2789b70ebd2f24c815f5f4Jean Chalard private boolean revertDoubleSpaceWhileInBatchEdit(final InputConnection ic) { 21394733609947c0ec74e460bd714fffca0518ade93aJean Chalard mHandler.cancelDoubleSpacesTimer(); 21404733609947c0ec74e460bd714fffca0518ade93aJean Chalard // Here we test whether we indeed have a period and a space before us. This should not 21414733609947c0ec74e460bd714fffca0518ade93aJean Chalard // be needed, but it's there just in case something went wrong. 21424733609947c0ec74e460bd714fffca0518ade93aJean Chalard final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0); 21438ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard if (!". ".equals(textBeforeCursor)) { 214451fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard // Theoretically we should not be coming here if there isn't ". " before the 214551fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard // cursor, but the application may be changing the text while we are typing, so 214651fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard // anything goes. We should not crash. 214751fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard Log.d(TAG, "Tried to revert double-space combo but we didn't find " 21488ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard + "\". \" just before the cursor."); 214951fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard return false; 21508ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard } 21514733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.deleteSurroundingText(2, 0); 21524733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.commitText(" ", 1); 21534733609947c0ec74e460bd714fffca0518ade93aJean Chalard return true; 21544733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 21554733609947c0ec74e460bd714fffca0518ade93aJean Chalard 21568fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka private static boolean revertSwapPunctuation(final InputConnection ic) { 2157120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Here we test whether we indeed have a space and something else before us. This should not 2158120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // be needed, but it's there just in case something went wrong. 2159120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0); 2160120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // NOTE: This does not work with surrogate pairs. Hopefully when the keyboard is able to 2161120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // enter surrogate pairs this code will have been removed. 21628be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard if (TextUtils.isEmpty(textBeforeCursor) 21638be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard || (Keyboard.CODE_SPACE != textBeforeCursor.charAt(1))) { 21648be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard // We may only come here if the application is changing the text while we are typing. 21658be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard // This is quite a broken case, but not logically impossible, so we shouldn't crash, 21668be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard // but some debugging log may be in order. 21678be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard Log.d(TAG, "Tried to revert a swap of punctuation but we didn't " 21688ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard + "find a space just before the cursor."); 21698be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard return false; 21708ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard } 2171120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.beginBatchEdit(); 2172120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.deleteSurroundingText(2, 0); 2173120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.commitText(" " + textBeforeCursor.subSequence(0, 1), 1); 2174120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.endBatchEdit(); 2175120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return true; 2176120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 2177120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 2178923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean isWordSeparator(int code) { 217917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard return mSettingsValues.isWordSeparator(code); 2180923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2181923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2182923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean preferCapitalization() { 21839318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa return mWordComposer.isFirstCharCapitalized(); 2184923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2185923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 218688fc9d44186120f9edc5cf7ec0e2af85260fed04satok // Notify that language or mode have been changed and toggleLanguage will update KeyboardID 2187c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // according to new language or mode. 2188c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka public void onRefreshKeyboard() { 218955303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) { 219055303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka // Before Honeycomb, Voice IME is in LatinIME and it changes the current input view, 219155303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka // so that we need to re-create the keyboard input view here. 219255303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka setInputView(mKeyboardSwitcher.onCreateInputView()); 219355303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka } 21941e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka // When the device locale is changed in SetupWizard etc., this method may get called via 21951e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka // onConfigurationChanged before SoftInputWindow is shown. 21961e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka if (mKeyboardSwitcher.getKeyboardView() != null) { 21971e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka // Reload keyboard because the current language has been changed. 21981e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettingsValues); 21991e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka } 22000ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 22013fe263fac6375836c48ce71da29f098b66eb4f11Jean Chalard updateCorrectionMode(); 220217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 2203b84ee82e66d608151fcf552c82e7765a74e47fb0Jean Chalard // Since we just changed languages, we should re-evaluate suggestions with whatever word 2204b84ee82e66d608151fcf552c82e7765a74e47fb0Jean Chalard // we are currently composing. If we are not composing anything, we may want to display 2205b84ee82e66d608151fcf552c82e7765a74e47fb0Jean Chalard // predictions or punctuation signs (which is done by updateBigramPredictions anyway). 2206b84ee82e66d608151fcf552c82e7765a74e47fb0Jean Chalard if (isCursorTouchingWord()) { 2207b84ee82e66d608151fcf552c82e7765a74e47fb0Jean Chalard mHandler.postUpdateSuggestions(); 2208b84ee82e66d608151fcf552c82e7765a74e47fb0Jean Chalard } else { 2209b84ee82e66d608151fcf552c82e7765a74e47fb0Jean Chalard mHandler.postUpdateBigramPredictions(); 2210b84ee82e66d608151fcf552c82e7765a74e47fb0Jean Chalard } 221136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 221236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 2213564496bad6207f02e7a653872213bc5954e84ce4Jean Chalard public void hapticAndAudioFeedback(final int primaryCode) { 2214544c3c29527927239a6484efc30bc22f9cc4dad1Jean Chalard mFeedbackManager.hapticAndAudioFeedback(primaryCode, mKeyboardSwitcher.getKeyboardView()); 2215d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka } 2216d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka 22175a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 22182a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka public void onPressKey(int primaryCode) { 2219a5c96f376ad57e78a88942bb618e067054ed818aTadashi G. Takaoka mKeyboardSwitcher.onPressKey(primaryCode); 2220923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2221923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 22225a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 22232a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka public void onReleaseKey(int primaryCode, boolean withSliding) { 22242a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka mKeyboardSwitcher.onReleaseKey(primaryCode, withSliding); 22258d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv 22268d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv // If accessibility is on, ensure the user receives keyboard state updates. 22278d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) { 22288d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv switch (primaryCode) { 22298d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case Keyboard.CODE_SHIFT: 22308d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv AccessibleKeyboardViewProxy.getInstance().notifyShiftState(); 22318d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv break; 22328d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: 22338d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv AccessibleKeyboardViewProxy.getInstance().notifySymbolsState(); 22348d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv break; 22358d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv } 22368d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv } 2237923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2238a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2239123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka // receive ringer mode change and network state change. 2240923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private BroadcastReceiver mReceiver = new BroadcastReceiver() { 2241923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 2242923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onReceive(Context context, Intent intent) { 2243123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final String action = intent.getAction(); 2244564496bad6207f02e7a653872213bc5954e84ce4Jean Chalard if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 2245123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka mSubtypeSwitcher.onNetworkStateChanged(intent); 224621af2f40c59de3ea5ec183aa278406bf28d5e3bdJean Chalard } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { 224721af2f40c59de3ea5ec183aa278406bf28d5e3bdJean Chalard mFeedbackManager.onRingerModeChanged(); 2248123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } 2249923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2250923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project }; 2251923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2252564496bad6207f02e7a653872213bc5954e84ce4Jean Chalard // TODO: remove this method when VoiceProxy has been removed 2253409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void vibrate() { 2254544c3c29527927239a6484efc30bc22f9cc4dad1Jean Chalard mFeedbackManager.vibrate(mKeyboardSwitcher.getKeyboardView()); 2255923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2256923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2257f7d6517d6b1a1dd88e2142e1a15703bb839be01bJean Chalard public boolean isAutoCapitalized() { 2258f7d6517d6b1a1dd88e2142e1a15703bb839be01bJean Chalard return mWordComposer.isAutoCapitalized(); 22596516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani } 22606516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani 2261e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private void updateCorrectionMode() { 22629f67e12a0e3f77985fb8bafe0db4c00e32317b9asatok // TODO: cleanup messy flags 2263f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled 2264dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard && !mInputAttributes.mInputTypeNoAutoCorrect; 2265283b0c2b642030539ba3e41f3f54b6aed6bb9e2dJean Chalard mCorrectionMode = shouldAutoCorrect ? Suggest.CORRECTION_FULL : Suggest.CORRECTION_NONE; 2266283b0c2b642030539ba3e41f3f54b6aed6bb9e2dJean Chalard mCorrectionMode = (mSettingsValues.mBigramSuggestionEnabled && shouldAutoCorrect) 2267979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ? Suggest.CORRECTION_FULL_BIGRAM : mCorrectionMode; 2268e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 2269e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani 22702ac5988f84b5c38d313951a3d7faddebf5f25e04Tadashi G. Takaoka private void updateSuggestionVisibility(final Resources res) { 22710fe3611bee5095e7bd0fff2d0fdf8d5a13379132Jean Chalard final String suggestionVisiblityStr = mSettingsValues.mShowSuggestionsSetting; 22727599cfea4a2d56f4779452ec8e8742f7b9629cc0satok for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) { 2273458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa if (suggestionVisiblityStr.equals(res.getString(visibility))) { 22747599cfea4a2d56f4779452ec8e8742f7b9629cc0satok mSuggestionVisibility = visibility; 22757599cfea4a2d56f4779452ec8e8742f7b9629cc0satok break; 22767599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 22777599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 22787599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 22797599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 2280466741d8a78965b8509bf527344f289e50873092Mike LeBeau protected void launchSettings() { 2281cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa launchSettingsClass(Settings.class); 2282466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 2283466741d8a78965b8509bf527344f289e50873092Mike LeBeau 2284bf96661d33d0126adb60a48880ceba1ff055d4a4satok public void launchDebugSettings() { 2285cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa launchSettingsClass(DebugSettings.class); 2286bf96661d33d0126adb60a48880ceba1ff055d4a4satok } 2287bf96661d33d0126adb60a48880ceba1ff055d4a4satok 2288cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa protected void launchSettingsClass(Class<? extends PreferenceActivity> settingsClass) { 2289923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project handleClose(); 2290923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Intent intent = new Intent(); 2291466741d8a78965b8509bf527344f289e50873092Mike LeBeau intent.setClass(LatinIME.this, settingsClass); 2292923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2293923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project startActivity(intent); 2294923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2295923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 22962fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showSubtypeSelectorAndSettings() { 229785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 229885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 229985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka // TODO: Should use new string "Select active input modes". 230085996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.language_selection_title), 230185996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 230285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 230385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 23042fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka @Override 23052fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka public void onClick(DialogInterface di, int position) { 23062fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka di.dismiss(); 23072fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka switch (position) { 230885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 23092cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok Intent intent = CompatUtils.getInputLanguageSelectionIntent( 2310cc8c8b99bd0463f5977dea82f5e2379ea1dd4e73Tadashi G. Takaoka SubtypeUtils.getInputMethodId(getPackageName()), 23112a659b8aa642b0832fa0ac9a93e0640592fcc239Jean Chalard Intent.FLAG_ACTIVITY_NEW_TASK 23122fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 23132fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_CLEAR_TOP); 23142fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka startActivity(intent); 23152fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2316aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa case 1: 2317aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa launchSettings(); 2318aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa break; 23192fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 23202fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 232185996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 2322bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka final AlertDialog.Builder builder = new AlertDialog.Builder(this) 2323bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setItems(items, listener) 2324bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setTitle(title); 2325bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka showOptionDialogInternal(builder.create()); 23262fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 2327923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 23282fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showOptionsMenu() { 232985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 233085996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 233185996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.selectInputMethod), 233285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 233385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 233485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 23355a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 2336923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onClick(DialogInterface di, int position) { 2337923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project di.dismiss(); 2338923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (position) { 233985996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 2340ea55bf5df7d26d12b36c47141bfbac5730c3929aTadashi G. Takaoka mImm.showInputMethodPicker(); 23412fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 234285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 1: 2343ea55bf5df7d26d12b36c47141bfbac5730c3929aTadashi G. Takaoka launchSettings(); 23442fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2345923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2346923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 234785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 2348bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka final AlertDialog.Builder builder = new AlertDialog.Builder(this) 2349bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setItems(items, listener) 2350bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setTitle(title); 2351bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka showOptionDialogInternal(builder.create()); 2352923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2353923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 23547e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 23557e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 2356923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.dump(fd, fout, args); 2357a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2358923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final Printer p = new PrintWriterPrinter(fout); 2359923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println("LatinIME state :"); 23603708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); 2361df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka final int keyboardMode = keyboard != null ? keyboard.mId.mMode : -1; 2362df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka p.println(" Keyboard mode = " + keyboardMode); 2363dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard p.println(" mIsSuggestionsRequested=" + mInputAttributes.mIsSettingsSuggestionStripOn); 2364923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mCorrectionMode=" + mCorrectionMode); 23654d0f03bd66742ee292da81a3e025e119f28b6940Jean Chalard p.println(" isComposingWord=" + mWordComposer.isComposingWord()); 236617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mAutoCorrectEnabled=" + mSettingsValues.mAutoCorrectEnabled); 236717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mSoundOn=" + mSettingsValues.mSoundOn); 236817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mVibrateOn=" + mSettingsValues.mVibrateOn); 2369240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard p.println(" mKeyPreviewPopupOn=" + mSettingsValues.mKeyPreviewPopupOn); 23706fa003ee234c6e2ca6cd9ec555221ac5c71a5405Jean Chalard p.println(" mInputAttributes=" + mInputAttributes.toString()); 2371923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2372923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 2373