LatinIME.java revision bf7dd47329c23c846912b268d15e8083ffdaabde
1923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/* 2443c360d0afdbab091994244f045f4756feaf2b4Jean-Baptiste Queru * Copyright (C) 2008 The Android Open Source Project 3c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * 4923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * use this file except in compliance with the License. You may obtain a copy of 6923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License at 7a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker * 8923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker * 10923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * License for the specific language governing permissions and limitations under 14923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License. 15923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 16923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 17923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectpackage com.android.inputmethod.latin; 18923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 19923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.app.AlertDialog; 20923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.BroadcastReceiver; 21923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Context; 22923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.DialogInterface; 23923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Intent; 24923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.IntentFilter; 25923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.SharedPreferences; 26923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.res.Configuration; 2736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasaniimport android.content.res.Resources; 28923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.inputmethodservice.InputMethodService; 29923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.media.AudioManager; 30123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaokaimport android.net.ConnectivityManager; 31923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Debug; 32923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Message; 33923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.SystemClock; 34bf96661d33d0126adb60a48880ceba1ff055d4a4satokimport android.preference.PreferenceActivity; 35923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.preference.PreferenceManager; 36e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaokaimport android.text.InputType; 37923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.text.TextUtils; 38979f8690967ff5409fe18f5085858ccdb8e0ccf1satokimport android.util.DisplayMetrics; 39923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Log; 40923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.PrintWriterPrinter; 41923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Printer; 4266a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasaniimport android.view.HapticFeedbackConstants; 43923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.KeyEvent; 44923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.View; 458e09172df1bb176cc899940862c56bed9b9aec4esatokimport android.view.ViewGroup; 468e09172df1bb176cc899940862c56bed9b9aec4esatokimport android.view.ViewParent; 47923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.CompletionInfo; 48923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.EditorInfo; 49466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport android.view.inputmethod.ExtractedText; 50923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.InputConnection; 51c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka 525ac4638f999db4fea8a9e24171dbceb640a10858Alan Viveretteimport com.android.inputmethod.accessibility.AccessibilityUtils; 53c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.CompatUtils; 54c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.EditorInfoCompatUtils; 55c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputConnectionCompatUtils; 56c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputMethodManagerCompatWrapper; 57c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputMethodServiceCompatWrapper; 58c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputTypeCompatUtils; 591fef530ec7626fa16777f52b48191e61db8f46d4satokimport com.android.inputmethod.compat.SuggestionSpanUtils; 60c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.deprecated.LanguageSwitcherProxy; 61c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.deprecated.VoiceProxy; 62c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.deprecated.recorrection.Recorrection; 6383ffff2a49beeb41874b7cb40819a75001f708e2Ken Wakasaimport com.android.inputmethod.keyboard.Key; 64c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.Keyboard; 65c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardActionListener; 66c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardSwitcher; 67055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardSwitcher.KeyboardLayoutState; 68f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardView; 69c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.LatinKeyboard; 70c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.LatinKeyboardView; 71923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 72466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.FileDescriptor; 73466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.PrintWriter; 74466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.Locale; 75466741d8a78965b8509bf527344f289e50873092Mike LeBeau 76923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/** 77923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Input method implementation for Qwerty'ish keyboard. 78923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 79c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaokapublic class LatinIME extends InputMethodServiceCompatWrapper implements KeyboardActionListener, 80c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka CandidateView.Listener { 818efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka private static final String TAG = LatinIME.class.getSimpleName(); 82979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private static final boolean PERF_DEBUG = false; 83409220583333bdf06290dd9fd42f91b5c0d1b11asatok private static final boolean TRACE = false; 849e2d810dc524380ca1db6b384cfb00b4401585e5Tadashi G. Takaoka private static boolean DEBUG; 85a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 868efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka /** 878efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * The private IME option used to indicate that no microphone should be 888efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * shown for a given text field. For instance, this is specified by the 898efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * search dialog when the dialog is already showing a voice search button. 908efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * 918efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * @deprecated Use {@link LatinIME#IME_OPTION_NO_MICROPHONE} with package name prefixed. 928efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka */ 9310dd34de0ffcde0104f7d2dae3a3c9fd66abffccsatok @SuppressWarnings("dep-ann") 948efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka public static final String IME_OPTION_NO_MICROPHONE_COMPAT = "nm"; 958efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka 968efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka /** 978efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * The private IME option used to indicate that no microphone should be 988efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * shown for a given text field. For instance, this is specified by the 998efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka * search dialog when the dialog is already showing a voice search button. 1008efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka */ 1014199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka public static final String IME_OPTION_NO_MICROPHONE = "noMicrophoneKey"; 1024199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka 1034199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka /** 1044199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka * The private IME option used to indicate that no settings key should be 1054199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka * shown for a given text field. 1064199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka */ 1074199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka public static final String IME_OPTION_NO_SETTINGS_KEY = "noSettingsKey"; 1088efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka 1099e347d3d448e48229c46aad394ec9bd60cd5807bsatok private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100; 110fd0bd57deb53c4cce32810a61133fa44b45dbb7bKen Wakasa 111923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // How many continuous deletes at which to start deleting at a higher speed. 112923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int DELETE_ACCELERATE_AT = 20; 113923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Key events coming any faster than this are long-presses. 114d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani private static final int QUICK_PRESS = 200; 115a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 116055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka private static final int SCREEN_ORIENTATION_CHANGE_DETECTION_DELAY = 2; 117055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka private static final int ACCUMULATE_START_INPUT_VIEW_DELAY = 20; 118de30f9f2d61c8dd06a150dbd7c71b560e8589a04Ken Wakasa private static final int RESTORE_KEYBOARD_STATE_DELAY = 500; 119055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 120cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard /** 121cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard * The name of the scheme used by the Package Manager to warn of a new package installation, 122cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard * replacement or removal. 123cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard */ 124cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard private static final String SCHEME_PACKAGE = "package"; 125cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 1267599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private int mSuggestionVisibility; 1277599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_VALUE 1287599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_value; 1297599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 1307599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_only_portrait_value; 1317599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_HIDE_VALUE 1327599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_hide_value; 1337599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 1347599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int[] SUGGESTION_VISIBILITY_VALUE_ARRAY = new int[] { 1357599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_VALUE, 1367599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE, 1377599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_HIDE_VALUE 1387599cfea4a2d56f4779452ec8e8742f7b9629cc0satok }; 1397599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 14017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard private Settings.Values mSettingsValues; 14117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 142e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka private View mCandidateViewContainer; 1437a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka private int mCandidateStripHeight; 144923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private CandidateView mCandidateView; 145923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private Suggest mSuggest; 1461b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka private CompletionInfo[] mApplicationSpecifiedCompletions; 147a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 148610f1dc8553cf2ed97e763a06a19380c4a6cd636satok private InputMethodManagerCompatWrapper mImm; 1492fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private Resources mResources; 1502fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private SharedPreferences mPrefs; 1512fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private String mInputMethodId; 15271c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka private KeyboardSwitcher mKeyboardSwitcher; 1530ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private SubtypeSwitcher mSubtypeSwitcher; 154b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok private VoiceProxy mVoiceProxy; 1557a8dac55278cedd838be325f56b4c52d973c61f5satok private Recorrection mRecorrection; 156a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 157923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private UserDictionary mUserDictionary; 158979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private UserBigramDictionary mUserBigramDictionary; 159f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard private UserUnigramDictionary mUserUnigramDictionary; 160ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka private boolean mIsUserDictionaryAvaliable; 16136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 1620730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard // TODO: Create an inner class to group options and pseudo-options to improve readability. 163c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // These variables are initialized according to the {@link EditorInfo#inputType}. 1640730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard private boolean mShouldInsertMagicSpace; 165c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mInputTypeNoAutoCorrect; 166c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mIsSettingsSuggestionStripOn; 167c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka private boolean mApplicationSpecifiedCompletionOn; 168c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 1699318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa private final StringBuilder mComposingStringBuilder = new StringBuilder(); 1709318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa private WordComposer mWordComposer = new WordComposer(); 171923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private CharSequence mBestWord; 172f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard private boolean mHasUncommittedTypedChars; 1730730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard // Magic space: a space that should disappear on space/apostrophe insertion, move after the 1740730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard // punctuation on punctuation insertion, and become a real space on alpha char insertion. 1750730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard private boolean mJustAddedMagicSpace; // This indicates whether the last char is a magic space. 1764733609947c0ec74e460bd714fffca0518ade93aJean Chalard // This indicates whether the last keypress resulted in processing of double space replacement 1774733609947c0ec74e460bd714fffca0518ade93aJean Chalard // with period-space. 1784733609947c0ec74e460bd714fffca0518ade93aJean Chalard private boolean mJustReplacedDoubleSpace; 179409220583333bdf06290dd9fd42f91b5c0d1b11asatok 18079efbed76f638be298493107fa2d0cd1b5eb529esatok private int mCorrectionMode; 18179efbed76f638be298493107fa2d0cd1b5eb529esatok private int mCommittedLength; 182979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Keep track of the last selection range to decide if we need to show word alternatives 18379efbed76f638be298493107fa2d0cd1b5eb529esatok private int mLastSelectionStart; 18479efbed76f638be298493107fa2d0cd1b5eb529esatok private int mLastSelectionEnd; 185979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1864733609947c0ec74e460bd714fffca0518ade93aJean Chalard // Whether we are expecting an onUpdateSelection event to fire. If it does when we don't 1874733609947c0ec74e460bd714fffca0518ade93aJean Chalard // "expect" it, it means the user actually moved the cursor. 1884733609947c0ec74e460bd714fffca0518ade93aJean Chalard private boolean mExpectingUpdateSelection; 189923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mDeleteCount; 190923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastKeyTime; 191a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 192923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private AudioManager mAudioManager; 193bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa private static float mFxVolume = -1.0f; // just a default value to be updated runtime 19417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard private boolean mSilentModeOn; // System-wide current configuration 195923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 196b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok // TODO: Move this flag to VoiceProxy 19781c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani private boolean mConfigurationChanging; 198466741d8a78965b8509bf527344f289e50873092Mike LeBeau 19938f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka // Member variables for remembering the current device orientation. 20038f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka private int mDisplayOrientation; 20138f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka private int mDisplayWidth; 20238f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka private int mDisplayHeight; 20338f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 204cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Object for reacting to adding/removing a dictionary pack. 205cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard private BroadcastReceiver mDictionaryPackInstallReceiver = 206cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard new DictionaryPackInstallBroadcastReceiver(this); 207cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 208dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Keeps track of most recently inserted text (multi-character key) for reverting 209dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani private CharSequence mEnteredText; 210dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 2114f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public final UIHandler mHandler = new UIHandler(this); 212d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 2134f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public static class UIHandler extends StaticInnerHandlerWrapper<LatinIME> { 214d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_SUGGESTIONS = 0; 215d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_OLD_SUGGESTIONS = 1; 216d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_UPDATE_SHIFT_STATE = 2; 217d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka private static final int MSG_VOICE_RESULTS = 3; 218de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 4; 219de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 5; 220fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka private static final int MSG_SPACE_TYPED = 6; 221cb3320179d39a7983874697a0aa428b127675c9dJean Chalard private static final int MSG_SET_BIGRAM_PREDICTIONS = 7; 22238f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka private static final int MSG_CONFIRM_ORIENTATION_CHANGE = 8; 22338f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka private static final int MSG_START_INPUT_VIEW = 9; 224055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka private static final int MSG_RESTORE_KEYBOARD_LAYOUT = 10; 22538f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 22638f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka private static class OrientationChangeArgs { 22738f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka public final int mOldWidth; 22838f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka public final int mOldHeight; 22938f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka private int mRetryCount; 23038f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 23138f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka public OrientationChangeArgs(int oldw, int oldh) { 23238f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka mOldWidth = oldw; 23338f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka mOldHeight = oldh; 23438f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka mRetryCount = 0; 23538f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 23638f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 23738f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka public boolean hasTimedOut() { 23838f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka mRetryCount++; 23938f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka return mRetryCount >= 10; 24038f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 24138f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 24238f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka public boolean hasOrientationChangeFinished(DisplayMetrics dm) { 24338f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka return dm.widthPixels != mOldWidth && dm.heightPixels != mOldHeight; 24438f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 24538f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 246d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 2474f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public UIHandler(LatinIME outerInstance) { 2484f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa super(outerInstance); 2494f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa } 2504f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa 251923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 252923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void handleMessage(Message msg) { 2534f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final LatinIME latinIme = getOuterInstance(); 2544f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final KeyboardSwitcher switcher = latinIme.mKeyboardSwitcher; 255c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka final LatinKeyboardView inputView = switcher.getKeyboardView(); 256923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (msg.what) { 257d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SUGGESTIONS: 2584f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.updateSuggestions(); 259d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 260d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_OLD_SUGGESTIONS: 2614f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mRecorrection.fetchAndDisplayRecorrectionSuggestions( 2624f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mVoiceProxy, latinIme.mCandidateView, 2639318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa latinIme.mSuggest, latinIme.mKeyboardSwitcher, latinIme.mWordComposer, 2644f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mHasUncommittedTypedChars, latinIme.mLastSelectionStart, 2654f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mLastSelectionEnd, latinIme.mSettingsValues.mWordSeparators); 266d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 267d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SHIFT_STATE: 268de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka switcher.updateShiftState(); 269d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 270cb3320179d39a7983874697a0aa428b127675c9dJean Chalard case MSG_SET_BIGRAM_PREDICTIONS: 2714f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.updateBigramPredictions(); 27289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard break; 273d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_VOICE_RESULTS: 2744f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mVoiceProxy.handleVoiceResults(latinIme.preferCapitalization() 275de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked())); 276de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka break; 277de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka case MSG_FADEOUT_LANGUAGE_ON_SPACEBAR: 27817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (inputView != null) { 27966432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka inputView.setSpacebarTextFadeFactor( 2804f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa (1.0f + latinIme.mSettingsValues. 2814f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa mFinalFadeoutFactorOfLanguageOnSpacebar) / 2, 28266432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka (LatinKeyboard)msg.obj); 28317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 284de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_DISMISS_LANGUAGE_ON_SPACEBAR, msg.obj), 2854f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mSettingsValues.mDurationOfFadeoutLanguageOnSpacebar); 286de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka break; 287de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka case MSG_DISMISS_LANGUAGE_ON_SPACEBAR: 28817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (inputView != null) { 28966432cfc9b7680a653bcf19d0d4250db21155eceTadashi G. Takaoka inputView.setSpacebarTextFadeFactor( 2904f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar, 29117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard (LatinKeyboard)msg.obj); 29217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 293d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 29438f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka case MSG_CONFIRM_ORIENTATION_CHANGE: { 29538f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka final OrientationChangeArgs args = (OrientationChangeArgs)msg.obj; 29638f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka final Resources res = latinIme.mResources; 29738f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka final DisplayMetrics dm = res.getDisplayMetrics(); 29838f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka if (args.hasTimedOut() || args.hasOrientationChangeFinished(dm)) { 29938f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka latinIme.setDisplayGeometry(res.getConfiguration(), dm); 30038f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } else { 30138f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka // It seems orientation changing is on going. 30238f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka postConfirmOrientationChange(args); 30338f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 30438f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka break; 30538f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 30638f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka case MSG_START_INPUT_VIEW: 30738f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka latinIme.onStartInputView((EditorInfo)msg.obj, false); 30838f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka break; 309055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka case MSG_RESTORE_KEYBOARD_LAYOUT: 310055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 311055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka ((KeyboardLayoutState)msg.obj).restore(); 312055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka break; 313923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 314923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 315d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 316d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateSuggestions() { 317d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 3189b2192bfd2d3a06df3c685ed4287e192dbaabf32Ken Wakasa sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS), 3194f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa getOuterInstance().mSettingsValues.mDelayUpdateSuggestions); 320d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 321d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 322d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateSuggestions() { 323d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 324d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 325d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 326d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public boolean hasPendingUpdateSuggestions() { 327d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka return hasMessages(MSG_UPDATE_SUGGESTIONS); 328d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 329d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 330d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateOldSuggestions() { 331d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_OLD_SUGGESTIONS); 332d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_OLD_SUGGESTIONS), 3334f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa getOuterInstance().mSettingsValues.mDelayUpdateOldSuggestions); 334d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 335d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 336d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateOldSuggestions() { 337d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_OLD_SUGGESTIONS); 338d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 339d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 340d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateShiftKeyState() { 341d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 34217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE), 3434f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa getOuterInstance().mSettingsValues.mDelayUpdateShiftState); 344d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 345d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 346d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateShiftState() { 347d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 348d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 349d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 350cb3320179d39a7983874697a0aa428b127675c9dJean Chalard public void postUpdateBigramPredictions() { 351cb3320179d39a7983874697a0aa428b127675c9dJean Chalard removeMessages(MSG_SET_BIGRAM_PREDICTIONS); 3529b2192bfd2d3a06df3c685ed4287e192dbaabf32Ken Wakasa sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS), 3534f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa getOuterInstance().mSettingsValues.mDelayUpdateSuggestions); 35489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 35589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 356cb3320179d39a7983874697a0aa428b127675c9dJean Chalard public void cancelUpdateBigramPredictions() { 357cb3320179d39a7983874697a0aa428b127675c9dJean Chalard removeMessages(MSG_SET_BIGRAM_PREDICTIONS); 35889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 35989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 360d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void updateVoiceResults() { 361d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka sendMessage(obtainMessage(MSG_VOICE_RESULTS)); 362d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 363de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka 364d5a6b910e83de6dea3c5813cbf5e219abaccdf8aTadashi G. Takaoka public void startDisplayLanguageOnSpacebar(boolean localeChanged) { 3654f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final LatinIME latinIme = getOuterInstance(); 366de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka removeMessages(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR); 367de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka removeMessages(MSG_DISMISS_LANGUAGE_ON_SPACEBAR); 3684f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final LatinKeyboardView inputView = latinIme.mKeyboardSwitcher.getKeyboardView(); 369de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka if (inputView != null) { 3704f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final LatinKeyboard keyboard = latinIme.mKeyboardSwitcher.getLatinKeyboard(); 371c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka // The language is always displayed when the delay is negative. 372c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka final boolean needsToDisplayLanguage = localeChanged 3734f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa || latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar < 0; 374de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka // The language is never displayed when the delay is zero. 3754f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa if (latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar != 0) { 376c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka inputView.setSpacebarTextFadeFactor(needsToDisplayLanguage ? 1.0f 3774f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa : latinIme.mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar, 3784f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa keyboard); 37917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 380c5c57b506e97b334a394d23ed73c9597cb55707aTadashi G. Takaoka // The fadeout animation will start when the delay is positive. 3814f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa if (localeChanged 3824f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa && latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar > 0) { 383de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR, keyboard), 3844f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar); 385de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 386de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 387de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka } 388fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 389fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public void startDoubleSpacesTimer() { 390fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka removeMessages(MSG_SPACE_TYPED); 391fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED), 3924f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa getOuterInstance().mSettingsValues.mDoubleSpacesTurnIntoPeriodTimeout); 393fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 394fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 395fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public void cancelDoubleSpacesTimer() { 396fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka removeMessages(MSG_SPACE_TYPED); 397fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 398fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 399fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public boolean isAcceptingDoubleSpaces() { 400fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka return hasMessages(MSG_SPACE_TYPED); 401fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 40238f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 403055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka public void postRestoreKeyboardLayout() { 404055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 405055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka final KeyboardLayoutState state = latinIme.mKeyboardSwitcher.getKeyboardState(); 406055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka if (state.isValid()) { 407055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka removeMessages(MSG_RESTORE_KEYBOARD_LAYOUT); 408055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka sendMessageDelayed( 409055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka obtainMessage(MSG_RESTORE_KEYBOARD_LAYOUT, state), 410055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka RESTORE_KEYBOARD_STATE_DELAY); 411055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 412055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 413055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 41438f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka private void postConfirmOrientationChange(OrientationChangeArgs args) { 41538f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka removeMessages(MSG_CONFIRM_ORIENTATION_CHANGE); 416055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka // Will confirm whether orientation change has finished or not again. 417055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_CONFIRM_ORIENTATION_CHANGE, args), 418055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka SCREEN_ORIENTATION_CHANGE_DETECTION_DELAY); 41938f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 42038f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 42138f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka public void startOrientationChanging(int oldw, int oldh) { 42238f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka postConfirmOrientationChange(new OrientationChangeArgs(oldw, oldh)); 423055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 424055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka latinIme.mKeyboardSwitcher.getKeyboardState().save(); 425055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka postRestoreKeyboardLayout(); 42638f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 42738f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 42838f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka public boolean postStartInputView(EditorInfo attribute) { 42938f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka if (hasMessages(MSG_CONFIRM_ORIENTATION_CHANGE) || hasMessages(MSG_START_INPUT_VIEW)) { 43038f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka removeMessages(MSG_START_INPUT_VIEW); 431cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa // Postpone onStartInputView by ACCUMULATE_START_INPUT_VIEW_DELAY and see if 432cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa // orientation change has finished. 433055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_START_INPUT_VIEW, attribute), 434055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka ACCUMULATE_START_INPUT_VIEW_DELAY); 43538f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka return true; 43638f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 43738f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka return false; 43838f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 43938f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 44038f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 44138f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka private void setDisplayGeometry(Configuration conf, DisplayMetrics metric) { 44238f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka mDisplayOrientation = conf.orientation; 44338f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka mDisplayWidth = metric.widthPixels; 44438f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka mDisplayHeight = metric.heightPixels; 445d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 446923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 4477e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 4487e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka public void onCreate() { 44927d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 45027d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mPrefs = prefs; 45127d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa LatinImeLogger.init(this, prefs); 4526d9021527a38ba1e94225020389621a0d7227aa1satok LanguageSwitcherProxy.init(this, prefs); 453bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka InputMethodManagerCompatWrapper.init(this); 454ef5dfc480c7a3e3e34a20b7aacc731942e7a0578Tadashi G. Takaoka SubtypeSwitcher.init(this); 45527d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa KeyboardSwitcher.init(this, prefs); 4567a8dac55278cedd838be325f56b4c52d973c61f5satok Recorrection.init(this, prefs); 4575ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette AccessibilityUtils.init(this, prefs); 458363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 459923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onCreate(); 460363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 461bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka mImm = InputMethodManagerCompatWrapper.getInstance(); 4628efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka mInputMethodId = Utils.getInputMethodId(mImm, getPackageName()); 4630ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 4640ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mKeyboardSwitcher = KeyboardSwitcher.getInstance(); 4657a8dac55278cedd838be325f56b4c52d973c61f5satok mRecorrection = Recorrection.getInstance(); 4669e2d810dc524380ca1db6b384cfb00b4401585e5Tadashi G. Takaoka DEBUG = LatinImeLogger.sDBG; 467363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 46817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 46917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 470363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka final Resources res = getResources(); 471363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka mResources = res; 472fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard 4739502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Utils.GCUtils.getInstance().reset(); 474979f8690967ff5409fe18f5085858ccdb8e0ccf1satok boolean tryGC = true; 4759502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { 476979f8690967ff5409fe18f5085858ccdb8e0ccf1satok try { 4770ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 478979f8690967ff5409fe18f5085858ccdb8e0ccf1satok tryGC = false; 479979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } catch (OutOfMemoryError e) { 4809502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka tryGC = Utils.GCUtils.getInstance().tryGCOrWait("InitSuggest", e); 481979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 482979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 483979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 48438f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka setDisplayGeometry(res.getConfiguration(), res.getDisplayMetrics()); 485b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 486cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Register to receive ringer mode change and network state change. 487cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Also receive installation and removal of a dictionary pack. 488123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final IntentFilter filter = new IntentFilter(); 489123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); 490123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 491923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project registerReceiver(mReceiver, filter); 492b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy = VoiceProxy.init(this, prefs, mHandler); 493cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 494cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final IntentFilter packageFilter = new IntentFilter(); 495cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 496cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 497cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addDataScheme(SCHEME_PACKAGE); 498cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard registerReceiver(mDictionaryPackInstallReceiver, packageFilter); 499646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard 500646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard final IntentFilter newDictFilter = new IntentFilter(); 501646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard newDictFilter.addAction( 502646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard DictionaryPackInstallBroadcastReceiver.NEW_DICTIONARY_INTENT_ACTION); 503646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard registerReceiver(mDictionaryPackInstallReceiver, newDictFilter); 504923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 50536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 50617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // Has to be package-visible for unit tests 50717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard /* package */ void loadSettings() { 50817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this); 50917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (null == mSubtypeSwitcher) mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 51017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues = new Settings.Values(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr()); 51114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary()); 512bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa updateSoundEffectVolume(); 51317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 51417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 5150ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private void initSuggest() { 516cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); 517eaa10f44a4a0108a90803b1b28238842d3fb5addsatok final Locale keyboardLocale = Utils.constructLocaleFromString(localeStr); 51836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 519309bff562fbaf47488e6bf6636840f00574187d8Jean Chalard final Resources res = mResources; 520309bff562fbaf47488e6bf6636840f00574187d8Jean Chalard final Locale savedLocale = Utils.setSystemLocale(res, keyboardLocale); 52114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard final ContactsDictionary oldContactsDictionary; 52236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani if (mSuggest != null) { 52314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard oldContactsDictionary = mSuggest.getContactsDictionary(); 52436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani mSuggest.close(); 52514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } else { 52614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard oldContactsDictionary = null; 52736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 528979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 5298efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka int mainDicResId = Utils.getMainDictionaryResourceId(res); 530cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mSuggest = new Suggest(this, mainDicResId, keyboardLocale); 53117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.mAutoCorrectEnabled) { 53217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); 53317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 53427023341658b4cf5430d18ddb94fd9502ecfe3cbTadashi G. Takaoka updateAutoTextEnabled(); 535e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 536cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mUserDictionary = new UserDictionary(this, localeStr); 537923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mSuggest.setUserDictionary(mUserDictionary); 538ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka mIsUserDictionaryAvaliable = mUserDictionary.isEnabled(); 539e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 54014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard resetContactsDictionary(oldContactsDictionary); 541e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 542f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard mUserUnigramDictionary 543f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard = new UserUnigramDictionary(this, this, localeStr, Suggest.DIC_USER_UNIGRAM); 544f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard mSuggest.setUserUnigramDictionary(mUserUnigramDictionary); 545e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 546f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard mUserBigramDictionary 547f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard = new UserBigramDictionary(this, this, localeStr, Suggest.DIC_USER_BIGRAM); 548e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.setUserBigramDictionary(mUserBigramDictionary); 549e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 550e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani updateCorrectionMode(); 55136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 552309bff562fbaf47488e6bf6636840f00574187d8Jean Chalard Utils.setSystemLocale(res, savedLocale); 553923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 55436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 55514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard /** 55614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * Resets the contacts dictionary in mSuggest according to the user settings. 55714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * 55814051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * This method takes an optional contacts dictionary to use. Since the contacts dictionary 55914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * does not depend on the locale, it can be reused across different instances of Suggest. 56014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * The dictionary will also be opened or closed as necessary depending on the settings. 56114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * 56214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * @param oldContactsDictionary an optional dictionary to use, or null 56314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard */ 56414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard private void resetContactsDictionary(final ContactsDictionary oldContactsDictionary) { 56514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard final boolean shouldSetDictionary = (null != mSuggest && mSettingsValues.mUseContactsDict); 56614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard 56714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard final ContactsDictionary dictionaryToUse; 56814051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (!shouldSetDictionary) { 56914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // Make sure the dictionary is closed. If it is already closed, this is a no-op, 57014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // so it's safe to call it anyways. 57114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (null != oldContactsDictionary) oldContactsDictionary.close(); 57214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard dictionaryToUse = null; 57314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } else if (null != oldContactsDictionary) { 57414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // Make sure the old contacts dictionary is opened. If it is already open, this is a 57514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // no-op, so it's safe to call it anyways. 57614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard oldContactsDictionary.reopen(this); 57714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard dictionaryToUse = oldContactsDictionary; 57814051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } else { 57914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard dictionaryToUse = new ContactsDictionary(this, Suggest.DIC_CONTACTS); 58014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } 58114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard 58214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (null != mSuggest) { 58314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard mSuggest.setContactsDictionary(dictionaryToUse); 58414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } 585699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard } 586699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard 587cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard /* package private */ void resetSuggestMainDict() { 588cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); 589eaa10f44a4a0108a90803b1b28238842d3fb5addsatok final Locale keyboardLocale = Utils.constructLocaleFromString(localeStr); 590cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard int mainDicResId = Utils.getMainDictionaryResourceId(mResources); 591cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard mSuggest.resetMainDict(this, mainDicResId, keyboardLocale); 592cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard } 593cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 594466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 595466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onDestroy() { 596e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa if (mSuggest != null) { 597e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.close(); 598e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest = null; 599979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 600923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project unregisterReceiver(mReceiver); 601cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard unregisterReceiver(mDictionaryPackInstallReceiver); 602b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.destroy(); 603979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 604979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.onDestroy(); 605923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onDestroy(); 606923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 607923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 608923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 609923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onConfigurationChanged(Configuration conf) { 610dc64b138b5e3fb3706c0818d0a308fe6e36985b0Tadashi G. Takaoka mSubtypeSwitcher.onConfigurationChanged(conf); 611b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani // If orientation changed while predicting, commit the change 61238f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka if (conf.orientation != mDisplayOrientation) { 61338f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka mHandler.startOrientationChanging(mDisplayWidth, mDisplayHeight); 6149351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 615466741d8a78965b8509bf527344f289e50873092Mike LeBeau commitTyped(ic); 616466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (ic != null) ic.finishComposingText(); // For voice input 6172fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka if (isShowingOptionDialog()) 6182fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka mOptionsDialog.dismiss(); 619b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 6208b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 62181c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani mConfigurationChanging = true; 622923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onConfigurationChanged(conf); 623b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.onConfigurationChanged(conf); 62481c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani mConfigurationChanging = false; 62588fc9d44186120f9edc5cf7ec0e2af85260fed04satok 62688fc9d44186120f9edc5cf7ec0e2af85260fed04satok // This will work only when the subtype is not supported. 62788fc9d44186120f9edc5cf7ec0e2af85260fed04satok LanguageSwitcherProxy.onConfigurationChanged(conf); 628923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 629b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 630923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 631923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public View onCreateInputView() { 6326c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka return mKeyboardSwitcher.onCreateInputView(); 6336c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka } 6346c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka 6356c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka @Override 6366c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka public void setInputView(View view) { 6376c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka super.setInputView(view); 6386c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka mCandidateViewContainer = view.findViewById(R.id.candidates_container); 6396c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka mCandidateView = (CandidateView) view.findViewById(R.id.candidates); 640281e180c33b1dd88e8eae48f279736c529f529d2Tadashi G. Takaoka if (mCandidateView != null) 641281e180c33b1dd88e8eae48f279736c529f529d2Tadashi G. Takaoka mCandidateView.setListener(this, view); 642c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka mCandidateStripHeight = (int)mResources.getDimension(R.dimen.candidate_strip_height); 643923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 644923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 645923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 646c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka public void setCandidatesView(View view) { 647c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka // To ensure that CandidatesView will never be set. 648c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return; 649923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 650923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 651a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker @Override 652923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onStartInputView(EditorInfo attribute, boolean restarting) { 653055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka mHandler.postRestoreKeyboardLayout(); 65438f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka if (mHandler.postStartInputView(attribute)) { 65538f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka return; 65638f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 65738f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 65845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 659c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka LatinKeyboardView inputView = switcher.getKeyboardView(); 6608e09172df1bb176cc899940862c56bed9b9aec4esatok 66189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (DEBUG) { 662f0f726464dcb5b3cef4f8e703659b35ca62430b5Tadashi G. Takaoka Log.d(TAG, "onStartInputView: attribute:" + ((attribute == null) ? "none" 663f0f726464dcb5b3cef4f8e703659b35ca62430b5Tadashi G. Takaoka : String.format("inputType=0x%08x imeOptions=0x%08x", 664f0f726464dcb5b3cef4f8e703659b35ca62430b5Tadashi G. Takaoka attribute.inputType, attribute.imeOptions))); 665910b73127fa207dd26ec8124000262523b0aac0csatok } 666923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In landscape mode, this method gets called without the input view being created. 667979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (inputView == null) { 668923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 669923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 670923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 6718d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka mSubtypeSwitcher.updateParametersOnStartInputView(); 6724ab730dbd34fad323063f2ffd31ce33de746668dsatok 673662bb7c26cadd5026cb3d4e5d081aae163bd5a3aTadashi G. Takaoka TextEntryState.reset(); 6746c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani 675055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka // Most such things we decide below in initializeInputAttributesAndGetMode, but we need to 676055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka // know now whether this is a password text field, because we need to know now whether we 677055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka // want to enable the voice button. 678055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka final VoiceProxy voiceIme = mVoiceProxy; 6793be0039164f5e2060b83d0699e293ffc76384732Tadashi G. Takaoka final int inputType = (attribute != null) ? attribute.inputType : 0; 6803be0039164f5e2060b83d0699e293ffc76384732Tadashi G. Takaoka voiceIme.resetVoiceStates(InputTypeCompatUtils.isPasswordInputType(inputType) 6813be0039164f5e2060b83d0699e293ffc76384732Tadashi G. Takaoka || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)); 682c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 683cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka initializeInputAttributes(attribute); 684c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 685c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.closing(); 686c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mEnteredText = null; 6879318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mComposingStringBuilder.setLength(0); 688f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = false; 689c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mDeleteCount = 0; 6900730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mJustAddedMagicSpace = false; 6914733609947c0ec74e460bd714fffca0518ade93aJean Chalard mJustReplacedDoubleSpace = false; 692c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 69317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 69417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard updateCorrectionMode(); 69517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard updateAutoTextEnabled(); 69617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard updateSuggestionVisibility(mPrefs, mResources); 69717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 69817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSuggest != null && mSettingsValues.mAutoCorrectEnabled) { 69917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); 70017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 70117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mVoiceProxy.loadSettings(attribute, mPrefs); 70217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // This will work only when the subtype is not supported. 70317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard LanguageSwitcherProxy.loadSettings(); 70417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 705c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (mSubtypeSwitcher.isKeyboardMode()) { 706255486a5d067469e074f3649b3d2747e7a08aaa2Tadashi G. Takaoka switcher.loadKeyboard(attribute, mSettingsValues); 707c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 708c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 70988110d1799146943c627916ffaa94bbc4dd6f2aeTadashi G. Takaoka if (mCandidateView != null) 71088110d1799146943c627916ffaa94bbc4dd6f2aeTadashi G. Takaoka mCandidateView.clear(); 711c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShownInternal(isCandidateStripVisible(), /* needsInputViewShown */ false); 712c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // Delay updating suggestions because keyboard input view may not be shown at this point. 713c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mHandler.postUpdateSuggestions(); 714c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 715240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard inputView.setKeyPreviewPopupEnabled(mSettingsValues.mKeyPreviewPopupOn, 716240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard mSettingsValues.mKeyPreviewPopupDismissDelay); 717c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.setProximityCorrectionEnabled(true); 718c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // If we just entered a text field, maybe it has some old text that requires correction 7197a8dac55278cedd838be325f56b4c52d973c61f5satok mRecorrection.checkRecorrectionOnStart(); 720c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 721055265684bdc049db54c3ec2a7fa5404ff36a608Tadashi G. Takaoka voiceIme.onStartInputView(inputView.getWindowToken()); 722c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 723c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); 724c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 725c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 726cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka private void initializeInputAttributes(EditorInfo attribute) { 727cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if (attribute == null) 728cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka return; 7294b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka final int inputType = attribute.inputType; 730c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka final int variation = inputType & InputType.TYPE_MASK_VARIATION; 7310730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mShouldInsertMagicSpace = false; 732e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = false; 7339fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 7341b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletionOn = false; 7351b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletions = null; 736dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 737cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_MASK_CLASS) == InputType.TYPE_CLASS_TEXT) { 738cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = true; 739cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // Make sure that passwords are not displayed in candidate view 740e9957752bcaad048746c7a57bbd2c0a59e1918a0satok if (InputTypeCompatUtils.isPasswordInputType(inputType) 741e9957752bcaad048746c7a57bbd2c0a59e1918a0satok || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)) { 742cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 743cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 744e9957752bcaad048746c7a57bbd2c0a59e1918a0satok if (InputTypeCompatUtils.isEmailVariation(variation) 745cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) { 7460730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mShouldInsertMagicSpace = false; 747cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else { 7480730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mShouldInsertMagicSpace = true; 749cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 750e9957752bcaad048746c7a57bbd2c0a59e1918a0satok if (InputTypeCompatUtils.isEmailVariation(variation)) { 751cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 752cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) { 753cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 754cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) { 755cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 756cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } else if (variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) { 757cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // If it's a browser edit field and auto correct is not ON explicitly, then 758cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // disable auto correction, but keep suggestions on. 759cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) { 760e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mInputTypeNoAutoCorrect = true; 76136ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani } 762cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 763cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka 764cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // If NO_SUGGESTIONS is set, don't do prediction. 765cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) { 766cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 767cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mInputTypeNoAutoCorrect = true; 768cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 769cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka // If it's not multiline and the autoCorrect flag is not set, then don't correct 770cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 771cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka && (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { 772cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mInputTypeNoAutoCorrect = true; 773cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 774cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { 775cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mIsSettingsSuggestionStripOn = false; 776cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka mApplicationSpecifiedCompletionOn = isFullscreenMode(); 777cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka } 778923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 779923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 780923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 781923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 782e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka public void onWindowHidden() { 783e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka super.onWindowHidden(); 784f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 785e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka if (inputView != null) inputView.closing(); 786e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka } 787e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka 788e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka @Override 789923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onFinishInput() { 790923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onFinishInput(); 791a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 792979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 793979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 794b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.flushVoiceInputLogs(mConfigurationChanging); 795409220583333bdf06290dd9fd42f91b5c0d1b11asatok 796f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 797d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa if (inputView != null) inputView.closing(); 798f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard if (mUserUnigramDictionary != null) mUserUnigramDictionary.flushPendingWrites(); 799979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mUserBigramDictionary != null) mUserBigramDictionary.flushPendingWrites(); 800466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 801466741d8a78965b8509bf527344f289e50873092Mike LeBeau 802466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 8036495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa public void onFinishInputView(boolean finishingInput) { 8046495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa super.onFinishInputView(finishingInput); 805055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka mKeyboardSwitcher.onFinishInputView(); 806f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 8075f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka if (inputView != null) inputView.cancelAllMessages(); 808d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka // Remove pending messages related to update suggestions 809d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 810d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateOldSuggestions(); 8116495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa } 8126495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa 8136495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa @Override 814466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onUpdateExtractedText(int token, ExtractedText text) { 815466741d8a78965b8509bf527344f289e50873092Mike LeBeau super.onUpdateExtractedText(token, text); 816b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.showPunctuationHintIfNecessary(); 817923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 818923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 819923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 820923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onUpdateSelection(int oldSelStart, int oldSelEnd, 821923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int newSelStart, int newSelEnd, 822923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int candidatesStart, int candidatesEnd) { 823923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, 824923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project candidatesStart, candidatesEnd); 825466741d8a78965b8509bf527344f289e50873092Mike LeBeau 826466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (DEBUG) { 827466741d8a78965b8509bf527344f289e50873092Mike LeBeau Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart 828466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ose=" + oldSelEnd 829025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lss=" + mLastSelectionStart 830025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lse=" + mLastSelectionEnd 831466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nss=" + newSelStart 832466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nse=" + newSelEnd 833466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", cs=" + candidatesStart 834466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ce=" + candidatesEnd); 835466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 836466741d8a78965b8509bf527344f289e50873092Mike LeBeau 837b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.setCursorAndSelection(newSelEnd, newSelStart); 8384f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 839923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // If the current selection in the text view changes, we should 840923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // clear whatever candidate text we have. 841025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa final boolean selectionChanged = (newSelStart != candidatesEnd 842025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa || newSelEnd != candidatesEnd) && mLastSelectionStart != newSelStart; 843025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa final boolean candidatesCleared = candidatesStart == -1 && candidatesEnd == -1; 844f2f971531904026663a98629eec6eccf83e32fafJean Chalard if (!mExpectingUpdateSelection 845f2f971531904026663a98629eec6eccf83e32fafJean Chalard && ((mComposingStringBuilder.length() > 0 && mHasUncommittedTypedChars) 846b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok || mVoiceProxy.isVoiceInputHighlighted()) 847025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa && (selectionChanged || candidatesCleared)) { 848025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa if (candidatesCleared) { 849025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa // If the composing span has been cleared, save the typed word in the history for 850025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa // recorrection before we reset the candidate strip. Then, we'll be able to show 851025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa // suggestions for recorrection right away. 8529318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mRecorrection.saveRecorrectionSuggestion(mWordComposer, mComposingStringBuilder); 853025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa } 8549318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mComposingStringBuilder.setLength(0); 855f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = false; 85689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (isCursorTouchingWord()) { 857cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.cancelUpdateBigramPredictions(); 85889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.postUpdateSuggestions(); 85989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 86089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard setPunctuationSuggestions(); 86189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 862923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.reset(); 8639351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 864923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 865923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.finishComposingText(); 866923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 867b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.setVoiceInputHighlighted(false); 8688558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa } else if (!mHasUncommittedTypedChars && !mExpectingUpdateSelection 8698558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa && TextEntryState.isAcceptedDefault()) { 8708558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa TextEntryState.reset(); 871923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 8724733609947c0ec74e460bd714fffca0518ade93aJean Chalard if (!mExpectingUpdateSelection) { 8739318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mJustAddedMagicSpace = false; // The user moved the cursor. 8749318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mJustReplacedDoubleSpace = false; 8754733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 8764733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = false; 877d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateShiftKeyState(); 878466741d8a78965b8509bf527344f289e50873092Mike LeBeau 879979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Make a note of the cursor position 880979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionStart = newSelStart; 881979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionEnd = newSelEnd; 882466741d8a78965b8509bf527344f289e50873092Mike LeBeau 8837a8dac55278cedd838be325f56b4c52d973c61f5satok mRecorrection.updateRecorrectionSelection(mKeyboardSwitcher, 8847a8dac55278cedd838be325f56b4c52d973c61f5satok mCandidateView, candidatesStart, candidatesEnd, newSelStart, 8857a8dac55278cedd838be325f56b4c52d973c61f5satok newSelEnd, oldSelStart, mLastSelectionStart, 8867a8dac55278cedd838be325f56b4c52d973c61f5satok mLastSelectionEnd, mHasUncommittedTypedChars); 8877a8dac55278cedd838be325f56b4c52d973c61f5satok } 8887a8dac55278cedd838be325f56b4c52d973c61f5satok 8897a8dac55278cedd838be325f56b4c52d973c61f5satok public void setLastSelection(int start, int end) { 8907a8dac55278cedd838be325f56b4c52d973c61f5satok mLastSelectionStart = start; 8917a8dac55278cedd838be325f56b4c52d973c61f5satok mLastSelectionEnd = end; 892923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 893923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 894c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 895c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has clicked on the extracted text view, 896c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * when running in fullscreen mode. The default implementation hides 897c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * the candidates view when this happens, but only if the extracted text 898c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * editor has a vertical scroll bar because its text doesn't fit. 899c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 900c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * cause the candidate strip to disappear and re-appear. 901c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 902c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 903c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedTextClicked() { 9047a8dac55278cedd838be325f56b4c52d973c61f5satok if (mRecorrection.isRecorrectionEnabled() && isSuggestionsRequested()) return; 905c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 906c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedTextClicked(); 907c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 908c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 909c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 910c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has performed a cursor movement in the 911c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * extracted text view, when it is running in fullscreen mode. The default 912c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * implementation hides the candidates view when a vertical movement 913c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * happens, but only if the extracted text editor has a vertical scroll bar 914c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * because its text doesn't fit. 915c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 916c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * cause the candidate strip to disappear and re-appear. 917c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 918c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 919c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedCursorMovement(int dx, int dy) { 9207a8dac55278cedd838be325f56b4c52d973c61f5satok if (mRecorrection.isRecorrectionEnabled() && isSuggestionsRequested()) return; 921c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 922c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedCursorMovement(dx, dy); 923c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 924c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 925923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 926923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void hideWindow() { 927979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 928c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka mKeyboardSwitcher.onHideWindow(); 929979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 930923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (TRACE) Debug.stopMethodTracing(); 9316e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mOptionsDialog != null && mOptionsDialog.isShowing()) { 9326e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog.dismiss(); 9336e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog = null; 9346e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 935b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.hideVoiceWindow(mConfigurationChanging); 9369fbfd5877305ed19a20663630b498b6b3fdae942satok mRecorrection.clearWordsInHistory(); 937923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.hideWindow(); 938923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 939923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 940923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 9411b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka public void onDisplayCompletions(CompletionInfo[] applicationSpecifiedCompletions) { 942979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (DEBUG) { 943a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa Log.i(TAG, "Received completions:"); 944bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok if (applicationSpecifiedCompletions != null) { 945bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok for (int i = 0; i < applicationSpecifiedCompletions.length; i++) { 946bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok Log.i(TAG, " #" + i + ": " + applicationSpecifiedCompletions[i]); 947bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok } 948923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 949923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 9501b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (mApplicationSpecifiedCompletionOn) { 9511b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletions = applicationSpecifiedCompletions; 9521b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (applicationSpecifiedCompletions == null) { 953b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani clearSuggestions(); 954923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 955923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 956a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 9577e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords.Builder builder = new SuggestedWords.Builder() 9581b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka .setApplicationSpecifiedCompletions(applicationSpecifiedCompletions) 9595238df54ad3f648d09d5288f00b0a9d3c0593832Tadashi G. Takaoka .setTypedWordValid(false) 9605238df54ad3f648d09d5288f00b0a9d3c0593832Tadashi G. Takaoka .setHasMinimalSuggestion(false); 961979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // When in fullscreen mode, show completions generated by the application 9627e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(builder.build()); 963923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = null; 964c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShown(true); 965923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 966923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 967923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 968c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka private void setSuggestionStripShownInternal(boolean shown, boolean needsInputViewShown) { 9697a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // TODO: Modify this if we support candidates with hard keyboard 9707e9615f218630d14ae5666ede2efd5f12d0a23c3Tadashi G. Takaoka if (onEvaluateInputViewShown() && mCandidateViewContainer != null) { 9717a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka final boolean shouldShowCandidates = shown 9727a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka && (needsInputViewShown ? mKeyboardSwitcher.isInputViewShown() : true); 9734b1780fa9571409d65d9797d47949ffafaf0f083Tadashi G. Takaoka if (isFullscreenMode()) { 9747a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // No need to have extra space to show the key preview. 9757a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka mCandidateViewContainer.setMinimumHeight(0); 976c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka mCandidateViewContainer.setVisibility( 977c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka shouldShowCandidates ? View.VISIBLE : View.GONE); 9787a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka } else { 9797a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // We must control the visibility of the suggestion strip in order to avoid clipped 9807a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // key previews, even when we don't show the suggestion strip. 9817a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka mCandidateViewContainer.setVisibility( 9827a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka shouldShowCandidates ? View.VISIBLE : View.INVISIBLE); 9837a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka } 984923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 985923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 986a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 987c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka private void setSuggestionStripShown(boolean shown) { 988c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShownInternal(shown, /* needsInputViewShown */true); 989543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa } 990543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa 991543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa @Override 992923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onComputeInsets(InputMethodService.Insets outInsets) { 993923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onComputeInsets(outInsets); 994f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka final KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 9952951aa7e93c36fbbaff48139f3ff0ff6b67d05b7Tadashi G. Takaoka if (inputView == null || mCandidateViewContainer == null) 99646ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka return; 99746ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka final int containerHeight = mCandidateViewContainer.getHeight(); 99846ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka int touchY = containerHeight; 9999e347d3d448e48229c46aad394ec9bd60cd5807bsatok // Need to set touchable region only if input view is being shown 100046ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka if (mKeyboardSwitcher.isInputViewShown()) { 10017a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka if (mCandidateViewContainer.getVisibility() == View.VISIBLE) { 10027a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka touchY -= mCandidateStripHeight; 10039e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 10047a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka final int touchWidth = inputView.getWidth(); 10057a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka final int touchHeight = inputView.getHeight() + containerHeight 10067a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // Extend touchable region below the keyboard. 10077a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka + EXTENDED_TOUCHABLE_REGION_HEIGHT; 10089e347d3d448e48229c46aad394ec9bd60cd5807bsatok if (DEBUG) { 10097a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka Log.d(TAG, "Touchable region: y=" + touchY + " width=" + touchWidth 10107a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka + " height=" + touchHeight); 10119e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 10127a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka setTouchableRegionCompat(outInsets, 0, touchY, touchWidth, touchHeight); 10139e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 101446ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka outInsets.contentTopInsets = touchY; 101546ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka outInsets.visibleTopInsets = touchY; 1016923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1017a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1018923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 1019979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public boolean onEvaluateFullscreenMode() { 10202811841ab49b5c380a2e5b7f3e3d009db67f8e0aTadashi G. Takaoka final EditorInfo ei = getCurrentInputEditorInfo(); 10212811841ab49b5c380a2e5b7f3e3d009db67f8e0aTadashi G. Takaoka if (ei != null) { 10222811841ab49b5c380a2e5b7f3e3d009db67f8e0aTadashi G. Takaoka final int imeOptions = ei.imeOptions; 10232811841ab49b5c380a2e5b7f3e3d009db67f8e0aTadashi G. Takaoka if (EditorInfoCompatUtils.hasFlagNoFullscreen(imeOptions)) 10242811841ab49b5c380a2e5b7f3e3d009db67f8e0aTadashi G. Takaoka return false; 10252811841ab49b5c380a2e5b7f3e3d009db67f8e0aTadashi G. Takaoka if ((imeOptions & EditorInfo.IME_FLAG_NO_EXTRACT_UI) != 0) 10262811841ab49b5c380a2e5b7f3e3d009db67f8e0aTadashi G. Takaoka return false; 10272811841ab49b5c380a2e5b7f3e3d009db67f8e0aTadashi G. Takaoka } 1028458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa final Resources res = mResources; 1029458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa DisplayMetrics dm = res.getDisplayMetrics(); 1030979f8690967ff5409fe18f5085858ccdb8e0ccf1satok float displayHeight = dm.heightPixels; 1031979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // If the display is more than X inches high, don't go to fullscreen mode 1032458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa float dimen = res.getDimension(R.dimen.max_height_for_fullscreen); 1033979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (displayHeight > dimen) { 1034979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return false; 1035979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 1036979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return super.onEvaluateFullscreenMode(); 1037979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1038979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1039979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1040979f8690967ff5409fe18f5085858ccdb8e0ccf1satok @Override 1041923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 1042923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 1043e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_BACK: 1044c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka if (event.getRepeatCount() == 0 && mKeyboardSwitcher.getKeyboardView() != null) { 1045c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka if (mKeyboardSwitcher.getKeyboardView().handleBack()) { 10466e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani return true; 10476e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 1048e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 1049e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 1050923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1051923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyDown(keyCode, event); 1052923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1053923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1054923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 1055923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 1056923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (keyCode) { 1057e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_DOWN: 1058e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_UP: 1059e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_LEFT: 1060e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka case KeyEvent.KEYCODE_DPAD_RIGHT: 1061e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka // Enable shift key and DPAD to do selections 1062e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mKeyboardSwitcher.isInputViewShown() 1063e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka && mKeyboardSwitcher.isShiftedOrShiftLocked()) { 1064e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent newEvent = new KeyEvent(event.getDownTime(), event.getEventTime(), 1065e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getAction(), event.getKeyCode(), event.getRepeatCount(), 1066e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka event.getDeviceId(), event.getScanCode(), 1067e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON); 10689351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1069e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (ic != null) 1070e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka ic.sendKeyEvent(newEvent); 1071e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka return true; 1072e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 1073e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka break; 1074923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1075923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return super.onKeyUp(keyCode, event); 1076923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1077923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 10789351550dc6af7859e5280e16144c9386a37b976dKen Wakasa public void commitTyped(final InputConnection ic) { 10798558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa if (!mHasUncommittedTypedChars) return; 10808558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa mHasUncommittedTypedChars = false; 10818558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa if (mComposingStringBuilder.length() > 0) { 10829351550dc6af7859e5280e16144c9386a37b976dKen Wakasa if (ic != null) { 10839351550dc6af7859e5280e16144c9386a37b976dKen Wakasa ic.commitText(mComposingStringBuilder, 1); 1084923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 10858558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa mCommittedLength = mComposingStringBuilder.length(); 10868558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa TextEntryState.acceptedTyped(mComposingStringBuilder); 1087f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard addToUserUnigramAndBigramDictionaries(mComposingStringBuilder, 1088f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard UserUnigramDictionary.FREQUENCY_FOR_TYPED); 1089923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 10908558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa updateSuggestions(); 1091923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1092923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1093b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public boolean getCurrentAutoCapsState() { 10949351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 10951c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani EditorInfo ei = getCurrentInputEditorInfo(); 109617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.mAutoCap && ic != null && ei != null 109717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && ei.inputType != InputType.TYPE_NULL) { 1098b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return ic.getCursorCapsMode(ei.inputType) != 0; 10991c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 1100b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 11011c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 11021c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 1103863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard private void swapSwapperAndSpace() { 1104923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final InputConnection ic = getCurrentInputConnection(); 1105923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 1106923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence lastTwo = ic.getTextBeforeCursor(2, 0); 1107863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called. 1108923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastTwo != null && lastTwo.length() == 2 1109863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard && lastTwo.charAt(0) == Keyboard.CODE_SPACE) { 1110923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 1111923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 1112923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(lastTwo.charAt(1) + " ", 1); 1113923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1114b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 11154ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 11164ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 11174ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1118863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard private void maybeDoubleSpace() { 1119923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCorrectionMode == Suggest.CORRECTION_NONE) return; 1120923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final InputConnection ic = getCurrentInputConnection(); 1121923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 11222b4eabed2bfe982b91a994c145401d98894e6ef5Jean Chalard final CharSequence lastThree = ic.getTextBeforeCursor(3, 0); 1123923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastThree != null && lastThree.length() == 3 11249351550dc6af7859e5280e16144c9386a37b976dKen Wakasa && Utils.canBeFollowedByPeriod(lastThree.charAt(0)) 1125571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(1) == Keyboard.CODE_SPACE 1126fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka && lastThree.charAt(2) == Keyboard.CODE_SPACE 1127fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka && mHandler.isAcceptingDoubleSpaces()) { 1128fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka mHandler.cancelDoubleSpacesTimer(); 1129923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 1130923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 1131923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(". ", 1); 1132923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1133b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 11344733609947c0ec74e460bd714fffca0518ade93aJean Chalard mJustReplacedDoubleSpace = true; 1135fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } else { 1136fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka mHandler.startDoubleSpacesTimer(); 1137923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1138923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1139a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 11409351550dc6af7859e5280e16144c9386a37b976dKen Wakasa // "ic" must not null 11419351550dc6af7859e5280e16144c9386a37b976dKen Wakasa private void maybeRemovePreviousPeriod(final InputConnection ic, CharSequence text) { 114241a519729505a877844f2c57a33509c302dddbceKen Wakasa // When the text's first character is '.', remove the previous period 114341a519729505a877844f2c57a33509c302dddbceKen Wakasa // if there is one. 114441a519729505a877844f2c57a33509c302dddbceKen Wakasa CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 11454ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa if (lastOne != null && lastOne.length() == 1 1146571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastOne.charAt(0) == Keyboard.CODE_PERIOD 1147571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && text.charAt(0) == Keyboard.CODE_PERIOD) { 114841a519729505a877844f2c57a33509c302dddbceKen Wakasa ic.deleteSurroundingText(1, 0); 114941a519729505a877844f2c57a33509c302dddbceKen Wakasa } 115041a519729505a877844f2c57a33509c302dddbceKen Wakasa } 115141a519729505a877844f2c57a33509c302dddbceKen Wakasa 11529a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa private void removeTrailingSpace() { 11539a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa final InputConnection ic = getCurrentInputConnection(); 11549a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic == null) return; 11559a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa 11569a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 11579a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (lastOne != null && lastOne.length() == 1 1158571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastOne.charAt(0) == Keyboard.CODE_SPACE) { 11599a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.deleteSurroundingText(1, 0); 11609a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 11619a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 11629a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa 1163c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka @Override 1164923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean addWordToDictionary(String word) { 1165923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mUserDictionary.addWord(word, 128); 11666558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Suggestion strip should be updated after the operation of adding word to the 11676558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // user dictionary 1168d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1169923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1170923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1171923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1172923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean isAlphabet(int code) { 1173923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (Character.isLetter(code)) { 1174923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1175923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1176923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 1177923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1178923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1179a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1180e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka private void onSettingsKeyPressed() { 1181cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa if (isShowingOptionDialog()) return; 1182d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) { 1183d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka showSubtypeSelectorAndSettings(); 118411b7febc0bea46a6afb30d7fa040b841eadd7410Ken Wakasa } else if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm, false /* exclude aux subtypes */)) { 1185d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka showOptionsMenu(); 1186d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka } else { 1187d794c6f0788a65a4ec623de3f8f05122621d665fTadashi G. Takaoka launchSettings(); 11889a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 11899a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 11909a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 1191cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa // Virtual codes representing custom requests. These are used in onCustomRequest() below. 1192cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa public static final int CODE_SHOW_INPUT_METHOD_PICKER = 1; 1193cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa 1194cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa @Override 1195cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa public boolean onCustomRequest(int requestCode) { 1196cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa if (isShowingOptionDialog()) return false; 1197cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa switch (requestCode) { 1198cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa case CODE_SHOW_INPUT_METHOD_PICKER: 119911b7febc0bea46a6afb30d7fa040b841eadd7410Ken Wakasa if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm, true /* include aux subtypes */)) { 120079efbed76f638be298493107fa2d0cd1b5eb529esatok mImm.showInputMethodPicker(); 1201cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return true; 12029a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 1203cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return false; 12049a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 1205cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return false; 12069a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 12079a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 12089a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok private boolean isShowingOptionDialog() { 12099a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok return mOptionsDialog != null && mOptionsDialog.isShowing(); 12109a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 12119a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 12125f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // Implementation of {@link KeyboardActionListener}. 12135a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 12148aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { 1215923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long when = SystemClock.uptimeMillis(); 1216571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) { 1217923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mDeleteCount = 0; 1218923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1219923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastKeyTime = when; 1220b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 1221b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 12224733609947c0ec74e460bd714fffca0518ade93aJean Chalard final boolean lastStateOfJustReplacedDoubleSpace = mJustReplacedDoubleSpace; 12234733609947c0ec74e460bd714fffca0518ade93aJean Chalard mJustReplacedDoubleSpace = false; 1224923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 1225571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_DELETE: 12264733609947c0ec74e460bd714fffca0518ade93aJean Chalard handleBackspace(lastStateOfJustReplacedDoubleSpace); 12274189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka mDeleteCount++; 12284733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 12294189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka LatinImeLogger.logOnDelete(); 12304189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1231571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_SHIFT: 12324189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka // Shift key is handled in onPress() when device has distinct multi-touch panel. 1233101a00e3d4b1c29ef2ecdecd1b72b43efde7791aTadashi G. Takaoka if (!distinctMultiTouch) 1234b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.toggleShift(); 12354189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1236e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: 12374189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka // Symbol key is handled in onPress() when device has distinct multi-touch panel. 1238101a00e3d4b1c29ef2ecdecd1b72b43efde7791aTadashi G. Takaoka if (!distinctMultiTouch) 1239b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.changeKeyboardMode(); 12404189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1241571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_CANCEL: 12424189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka if (!isShowingOptionDialog()) { 12434189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka handleClose(); 12444189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 12454189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1246e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SETTINGS: 1247e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka onSettingsKeyPressed(); 12484189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1249571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_CAPSLOCK: 1250b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.toggleCapsLock(); 12514189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1252d2c5fdda862f6dd2a1e020cf674c35fbbc63fc92Tadashi G. Takaoka case Keyboard.CODE_SHORTCUT: 125320cdb37bd062ae6cb6d42ad6229a19733476cd55satok mSubtypeSwitcher.switchToShortcutIME(); 12544189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1255571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_TAB: 125645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka handleTab(); 12574733609947c0ec74e460bd714fffca0518ade93aJean Chalard // There are two cases for tab. Either we send a "next" event, that may change the 12584733609947c0ec74e460bd714fffca0518ade93aJean Chalard // focus but will never move the cursor. Or, we send a real tab keycode, which some 12594733609947c0ec74e460bd714fffca0518ade93aJean Chalard // applications may accept or ignore, and we don't know whether this will move the 12604733609947c0ec74e460bd714fffca0518ade93aJean Chalard // cursor or not. So actually, we don't really know. 12614733609947c0ec74e460bd714fffca0518ade93aJean Chalard // So to go with the safer option, we'd rather behave as if the user moved the 12624733609947c0ec74e460bd714fffca0518ade93aJean Chalard // cursor when they didn't than the opposite. We also expect that most applications 12634733609947c0ec74e460bd714fffca0518ade93aJean Chalard // will actually use tab only for focus movement. 12644733609947c0ec74e460bd714fffca0518ade93aJean Chalard // To sum it up: do not update mExpectingUpdateSelection here. 12654189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 12664189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka default: 126717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.isWordSeparator(primaryCode)) { 1268b5d17e52fcda39d540822e615bfb7ed5074e0034satok handleSeparator(primaryCode, x, y); 12694189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } else { 12708fbd55229243cb66c03d5ea1f79dfb39f596590dsatok handleCharacter(primaryCode, keyCodes, x, y); 12714189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 12724733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 12734733609947c0ec74e460bd714fffca0518ade93aJean Chalard break; 1274923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1275b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.onKey(primaryCode); 1276dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Reset after any single keystroke 1277dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = null; 1278923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1279a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 12805a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 12818aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onTextInput(CharSequence text) { 1282b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.commitVoiceInput(); 12839351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1284923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 12859fbfd5877305ed19a20663630b498b6b3fdae942satok mRecorrection.abortRecorrection(false); 1286923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 128755b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka commitTyped(ic); 12889351550dc6af7859e5280e16144c9386a37b976dKen Wakasa maybeRemovePreviousPeriod(ic, text); 1289923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(text, 1); 1290923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1291b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 12925f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka mKeyboardSwitcher.onKey(Keyboard.CODE_DUMMY); 12930730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mJustAddedMagicSpace = false; 1294dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = text; 1295923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1296923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 12975a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 12988aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCancelInput() { 129983e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka // User released a finger outside any key 13005f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka mKeyboardSwitcher.onCancelInput(); 130183e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka } 130283e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka 13034733609947c0ec74e460bd714fffca0518ade93aJean Chalard private void handleBackspace(boolean justReplacedDoubleSpace) { 1304b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok if (mVoiceProxy.logAndRevertVoiceInput()) return; 13054f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1306504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1307504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (ic == null) return; 1308979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.beginBatchEdit(); 1309979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1310b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleBackspace(); 13114f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 13129ae24750f462cbd94b362fe54a952c86cfb05e5fKen Wakasa final boolean deleteChar = !mHasUncommittedTypedChars; 1313f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (mHasUncommittedTypedChars) { 13149318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa final int length = mComposingStringBuilder.length(); 1315923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (length > 0) { 13169318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mComposingStringBuilder.delete(length - 1, length); 13179318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.deleteLast(); 13189318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa ic.setComposingText(mComposingStringBuilder, 1); 13199318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa if (mComposingStringBuilder.length() == 0) { 1320f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = false; 1321923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 132289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (1 == length) { 132389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // 1 == length means we are about to erase the last character of the word, 132489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // so we can show bigrams. 1325cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.postUpdateBigramPredictions(); 132689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 132789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // length > 1, so we still have letters to deduce a suggestion from. 132889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.postUpdateSuggestions(); 132989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 1330923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1331923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(1, 0); 1332923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1333923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1334d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateShiftKeyState(); 1335504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka 1336923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project TextEntryState.backspace(); 1337662bb7c26cadd5026cb3d4e5d081aae163bd5a3aTadashi G. Takaoka if (TextEntryState.isUndoCommit()) { 13389351550dc6af7859e5280e16144c9386a37b976dKen Wakasa revertLastWord(ic); 1339979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.endBatchEdit(); 1340923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1341504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka } 13424733609947c0ec74e460bd714fffca0518ade93aJean Chalard if (justReplacedDoubleSpace) { 13439351550dc6af7859e5280e16144c9386a37b976dKen Wakasa if (revertDoubleSpace(ic)) { 13449351550dc6af7859e5280e16144c9386a37b976dKen Wakasa ic.endBatchEdit(); 13459351550dc6af7859e5280e16144c9386a37b976dKen Wakasa return; 13464733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 13474733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 1348504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka 1349504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { 1350dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani ic.deleteSurroundingText(mEnteredText.length(), 0); 1351923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else if (deleteChar) { 13526558253160e2039c87f424bd814f402ecd31de3bKen Wakasa if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) { 13536558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Go back to the suggestion mode if the user canceled the 135455b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // "Touch again to save". 13556558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // NOTE: In gerenal, we don't revert the word when backspacing 13566558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // from a manual suggestion pick. We deliberately chose a 13576558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // different behavior only in the case of picking the first 13586558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // suggestion (typed word). It's intentional to have made this 13596558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // inconsistent with backspacing after selecting other suggestions. 13609351550dc6af7859e5280e16144c9386a37b976dKen Wakasa revertLastWord(ic); 13616558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } else { 1362923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 13636558253160e2039c87f424bd814f402ecd31de3bKen Wakasa if (mDeleteCount > DELETE_ACCELERATE_AT) { 13646558253160e2039c87f424bd814f402ecd31de3bKen Wakasa sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 13656558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 1366923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1367923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1368979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.endBatchEdit(); 1369923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1370923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 137145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka private void handleTab() { 137245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final int imeOptions = getCurrentInputEditorInfo().imeOptions; 1373b2707856aba4fc9b063f26305f1fb603b19c1701satok if (!EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) 1374b2707856aba4fc9b063f26305f1fb603b19c1701satok && !EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions)) { 137545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB); 137645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka return; 137745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 137845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 137945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 138045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (ic == null) 138145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka return; 138245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 138345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka // True if keyboard is in either chording shift or manual temporary upper case mode. 138445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final boolean isManualTemporaryUpperCase = mKeyboardSwitcher.isManualTemporaryUpperCase(); 1385b2707856aba4fc9b063f26305f1fb603b19c1701satok if (EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) 138645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka && !isManualTemporaryUpperCase) { 1387b2707856aba4fc9b063f26305f1fb603b19c1701satok EditorInfoCompatUtils.performEditorActionNext(ic); 1388b2707856aba4fc9b063f26305f1fb603b19c1701satok } else if (EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions) 138945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka && isManualTemporaryUpperCase) { 1390b2707856aba4fc9b063f26305f1fb603b19c1701satok EditorInfoCompatUtils.performEditorActionPrevious(ic); 139145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 139245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 139345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka 13948fbd55229243cb66c03d5ea1f79dfb39f596590dsatok private void handleCharacter(int primaryCode, int[] keyCodes, int x, int y) { 1395b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleCharacter(); 13964f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 139717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mJustAddedMagicSpace && mSettingsValues.isMagicSpaceStripper(primaryCode)) { 13980730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard removeTrailingSpace(); 13990730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard } 14000730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard 1401863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard if (mLastSelectionStart == mLastSelectionEnd) { 14029fbfd5877305ed19a20663630b498b6b3fdae942satok mRecorrection.abortRecorrection(false); 1403b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 14044f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1405e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka int code = primaryCode; 14063889462439357fd76c0b82dfd52e1ca6e0bafd2dKen Wakasa if ((isAlphabet(code) || mSettingsValues.isSymbolExcludedFromWordSeparators(code)) 14073889462439357fd76c0b82dfd52e1ca6e0bafd2dKen Wakasa && isSuggestionsRequested() && !isCursorTouchingWord()) { 1408f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (!mHasUncommittedTypedChars) { 1409f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = true; 14109318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mComposingStringBuilder.setLength(0); 14119318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mRecorrection.saveRecorrectionSuggestion(mWordComposer, mBestWord); 14129318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.reset(); 14137e99a28dfcc14f5b19220442db972ca8d786b4feKen Wakasa clearSuggestions(); 1414923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1415923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 141635f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 1417f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (switcher.isShiftedOrShiftLocked()) { 1418eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT 1419eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani || keyCodes[0] > Character.MAX_CODE_POINT) { 1420eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani return; 1421eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani } 1422e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka code = keyCodes[0]; 1423e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (switcher.isAlphabetMode() && Character.isLowerCase(code)) { 142435f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka // In some locales, such as Turkish, Character.toUpperCase() may return a wrong 142535f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka // character because it doesn't take care of locale. 142635f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka final String upperCaseString = new String(new int[] {code}, 0, 1) 142735f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka .toUpperCase(mSubtypeSwitcher.getInputLocale()); 142835f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka if (upperCaseString.codePointCount(0, upperCaseString.length()) == 1) { 142935f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka code = upperCaseString.codePointAt(0); 143012a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka } else { 143112a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka // Some keys, such as [eszett], have upper case as multi-characters. 143235f20916e5348d7fa485ba8eb0a5cf2e67f4f354Tadashi G. Takaoka onTextInput(upperCaseString); 143312a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka return; 143412a4e08a6440c95f29dc04efe83515a4ed045487Tadashi G. Takaoka } 1435979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1436923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1437f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (mHasUncommittedTypedChars) { 14389318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa if (mComposingStringBuilder.length() == 0 && switcher.isAlphabetMode() 1439f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka && switcher.isShiftedOrShiftLocked()) { 14409318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.setFirstCharCapitalized(true); 1441923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 14429318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mComposingStringBuilder.append((char) code); 14439318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.add(code, keyCodes, x, y); 14449351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1445923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 14461c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani // If it's the first letter, make note of auto-caps state 14479318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa if (mWordComposer.size() == 1) { 14489318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.setAutoCapitalized(getCurrentAutoCapsState()); 14491c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 14509318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa ic.setComposingText(mComposingStringBuilder, 1); 1451923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1452d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1453923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1454e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka sendKeyChar((char)code); 1455923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 145617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mJustAddedMagicSpace && mSettingsValues.isMagicSpaceSwapper(primaryCode)) { 1457863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard swapSwapperAndSpace(); 1458863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } else { 1459863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard mJustAddedMagicSpace = false; 1460863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } 1461863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard 1462b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka switcher.updateShiftState(); 1463979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (LatinIME.PERF_DEBUG) measureCps(); 146417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard TextEntryState.typedCharacter((char) code, mSettingsValues.isWordSeparator(code), x, y); 1465923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1466923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1467b5d17e52fcda39d540822e615bfb7ed5074e0034satok private void handleSeparator(int primaryCode, int x, int y) { 1468b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleSeparator(); 14694f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 147055b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // Should dismiss the "Touch again to save" message when handling separator 14716558253160e2039c87f424bd814f402ecd31de3bKen Wakasa if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) { 1472cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.cancelUpdateBigramPredictions(); 1473d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 14746558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 14756558253160e2039c87f424bd814f402ecd31de3bKen Wakasa 1476923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project boolean pickedDefault = false; 1477923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Handle separator 14781b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1479923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1480923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 14819fbfd5877305ed19a20663630b498b6b3fdae942satok mRecorrection.abortRecorrection(false); 1482923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1483f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (mHasUncommittedTypedChars) { 1484923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In certain languages where single quote is a separator, it's better 1485a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker // not to auto correct, but accept the typed word. For instance, 1486923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // in Italian dov' should not be expanded to dove' because the elision 1487923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // requires the last vowel to be removed. 1488f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled 1489c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa && !mInputTypeNoAutoCorrect; 149017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (shouldAutoCorrect && primaryCode != Keyboard.CODE_SINGLE_QUOTE) { 1491b5d17e52fcda39d540822e615bfb7ed5074e0034satok pickedDefault = pickDefaultSuggestion(primaryCode); 1492923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1493923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project commitTyped(ic); 1494923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1495923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 14964ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1497863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard if (mJustAddedMagicSpace) { 149817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.isMagicSpaceSwapper(primaryCode)) { 1499863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard sendKeyChar((char)primaryCode); 1500863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard swapSwapperAndSpace(); 1501863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } else { 150217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.isMagicSpaceStripper(primaryCode)) removeTrailingSpace(); 1503863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard sendKeyChar((char)primaryCode); 1504863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard mJustAddedMagicSpace = false; 1505863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } 15060730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard } else { 15070730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard sendKeyChar((char)primaryCode); 15084ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 15094ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1510863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard if (isSuggestionsRequested() && primaryCode == Keyboard.CODE_SPACE) { 1511863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard maybeDoubleSpace(); 1512863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard } 1513863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard 1514b5d17e52fcda39d540822e615bfb7ed5074e0034satok TextEntryState.typedCharacter((char) primaryCode, true, x, y); 151589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 1516979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (pickedDefault) { 15179318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa CharSequence typedWord = mWordComposer.getTypedWord(); 151855b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka TextEntryState.backToAcceptedDefault(typedWord); 151955b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka if (!TextUtils.isEmpty(typedWord) && !typedWord.equals(mBestWord)) { 1520b2707856aba4fc9b063f26305f1fb603b19c1701satok InputConnectionCompatUtils.commitCorrection( 152189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard ic, mLastSelectionEnd - typedWord.length(), typedWord, mBestWord); 152255b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka if (mCandidateView != null) 152355b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka mCandidateView.onAutoCorrectionInverted(mBestWord); 152455b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka } 152589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 152689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (Keyboard.CODE_SPACE == primaryCode) { 152789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (!isCursorTouchingWord()) { 152889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.cancelUpdateSuggestions(); 152989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.cancelUpdateOldSuggestions(); 1530cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.postUpdateBigramPredictions(); 153189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 153289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 153389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Set punctuation right away. onUpdateSelection will fire but tests whether it is 153489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // already displayed or not, so it's okay. 153555b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka setPunctuationSuggestions(); 1536923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1537b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1538923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1539923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1540923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1541923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1542466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1543923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleClose() { 1544923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project commitTyped(getCurrentInputConnection()); 1545b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok mVoiceProxy.handleClose(); 1546923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project requestHideSelf(0); 1547c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 15481679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka if (inputView != null) 15491679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka inputView.closing(); 1550923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1551923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 15527a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isSuggestionsRequested() { 1553c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka return mIsSettingsSuggestionStripOn 1554c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka && (mCorrectionMode > 0 || isShowingSuggestionsStrip()); 1555923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1556a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 15577a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isShowingPunctuationList() { 155817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard return mSettingsValues.mSuggestPuncList == mCandidateView.getSuggestions(); 15597599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 15607599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 15617a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isShowingSuggestionsStrip() { 15627599cfea4a2d56f4779452ec8e8742f7b9629cc0satok return (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_VALUE) 15637599cfea4a2d56f4779452ec8e8742f7b9629cc0satok || (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 156438f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka && mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT); 15657599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 15667599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 15679fbfd5877305ed19a20663630b498b6b3fdae942satok public boolean isCandidateStripVisible() { 1568b5e00d5841b946de8970875231456228ae0eb6b1Ken Wakasa if (mCandidateView == null) 1569b5e00d5841b946de8970875231456228ae0eb6b1Ken Wakasa return false; 1570952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa if (mCandidateView.isShowingAddToDictionaryHint() || TextEntryState.isRecorrecting()) 15719fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 15729fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!isShowingSuggestionsStrip()) 15739fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return false; 15749fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (mApplicationSpecifiedCompletionOn) 15759fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 15769fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return isSuggestionsRequested(); 1577923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1578923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1579409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void switchToKeyboardView() { 1580060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (DEBUG) { 1581060efb6d82af1f896d90cb845c8ae07c726f85e1satok Log.d(TAG, "Switch to keyboard view."); 1582060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 1583c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka View v = mKeyboardSwitcher.getKeyboardView(); 1584060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (v != null) { 1585060efb6d82af1f896d90cb845c8ae07c726f85e1satok // Confirms that the keyboard view doesn't have parent view. 1586060efb6d82af1f896d90cb845c8ae07c726f85e1satok ViewParent p = v.getParent(); 1587060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (p != null && p instanceof ViewGroup) { 1588060efb6d82af1f896d90cb845c8ae07c726f85e1satok ((ViewGroup) p).removeView(v); 15895a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } 1590060efb6d82af1f896d90cb845c8ae07c726f85e1satok setInputView(v); 1591060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 1592c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShown(isCandidateStripVisible()); 1593060efb6d82af1f896d90cb845c8ae07c726f85e1satok updateInputViewShown(); 1594060efb6d82af1f896d90cb845c8ae07c726f85e1satok mHandler.postUpdateSuggestions(); 1595466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1596466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1597409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void clearSuggestions() { 15987e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(SuggestedWords.EMPTY); 1599466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1600466741d8a78965b8509bf527344f289e50873092Mike LeBeau 16017e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka public void setSuggestions(SuggestedWords words) { 1602466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (mCandidateView != null) { 16037e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka mCandidateView.setSuggestions(words); 16045e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka mKeyboardSwitcher.onAutoCorrectionStateChanged( 16055e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka words.hasWordAboveAutoCorrectionScoreThreshold()); 1606466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1607466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1608466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1609409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void updateSuggestions() { 1610923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Check if we have a suggestion engine attached. 16119fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if ((mSuggest == null || !isSuggestionsRequested()) 1612b86905943c0f1cadb2b3df9f2a58e7af84f6b27fsatok && !mVoiceProxy.isVoiceInputHighlighted()) { 1613923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1614923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1615466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1616f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (!mHasUncommittedTypedChars) { 1617ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setPunctuationSuggestions(); 1618923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1619923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1620979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 16219318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa final WordComposer wordComposer = mWordComposer; 16229f67e12a0e3f77985fb8bafe0db4c00e32317b9asatok // TODO: May need a better way of retrieving previous word 162340f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final InputConnection ic = getCurrentInputConnection(); 162440f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final CharSequence prevWord; 162540f7efc172928bdd6048e91421a766abe5b22996Jean Chalard if (null == ic) { 162640f7efc172928bdd6048e91421a766abe5b22996Jean Chalard prevWord = null; 162740f7efc172928bdd6048e91421a766abe5b22996Jean Chalard } else { 162840f7efc172928bdd6048e91421a766abe5b22996Jean Chalard prevWord = EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators); 162940f7efc172928bdd6048e91421a766abe5b22996Jean Chalard } 163040f7efc172928bdd6048e91421a766abe5b22996Jean Chalard // getSuggestedWordBuilder handles gracefully a null value of prevWord 163140f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder( 1632043f7841985916717f4fa821fe3e423daf3ff2f5Jean Chalard mKeyboardSwitcher.getKeyboardView(), wordComposer, prevWord, 1633043f7841985916717f4fa821fe3e423daf3ff2f5Jean Chalard mKeyboardSwitcher.getLatinKeyboard().getProximityInfo()); 1634923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 16358558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa boolean autoCorrectionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasAutoCorrection(); 16369318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa final CharSequence typedWord = wordComposer.getTypedWord(); 1637bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // Here, we want to promote a whitelisted word if exists. 1638bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean typedWordValid = AutoCorrection.isValidWordForAutoCorrection( 1639bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok mSuggest.getUnigramDictionaries(), typedWord, preferCapitalization()); 1640979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mCorrectionMode == Suggest.CORRECTION_FULL 1641979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { 16428558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa autoCorrectionAvailable |= typedWordValid; 1643923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 16444a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani // Don't auto-correct words with multiple capital letter 16458558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa autoCorrectionAvailable &= !wordComposer.isMostlyCaps(); 16468558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa autoCorrectionAvailable &= !TextEntryState.isRecorrecting(); 1647979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1648a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // Basically, we update the suggestion strip only when suggestion count > 1. However, 1649a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // there is an exception: We update the suggestion strip whenever typed word's length 1650f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // is 1 or typed word is found in dictionary, regardless of suggestion count. Actually, 1651f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // in most cases, suggestion count is 1 when typed word's length is 1, but we do always 1652f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // need to clear the previous state when the user starts typing a word (i.e. typed word's 1653f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // length == 1). 1654fe1a6d961cf039357f061482461e4d2e951ad346satok if (typedWord != null) { 1655fe1a6d961cf039357f061482461e4d2e951ad346satok if (builder.size() > 1 || typedWord.length() == 1 || typedWordValid 1656fe1a6d961cf039357f061482461e4d2e951ad346satok || mCandidateView.isShowingAddToDictionaryHint()) { 1657fe1a6d961cf039357f061482461e4d2e951ad346satok builder.setTypedWordValid(typedWordValid).setHasMinimalSuggestion( 16588558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa autoCorrectionAvailable); 1659fe1a6d961cf039357f061482461e4d2e951ad346satok } else { 1660fe1a6d961cf039357f061482461e4d2e951ad346satok final SuggestedWords previousSuggestions = mCandidateView.getSuggestions(); 1661fe1a6d961cf039357f061482461e4d2e951ad346satok if (previousSuggestions == mSettingsValues.mSuggestPuncList) 1662fe1a6d961cf039357f061482461e4d2e951ad346satok return; 1663fe1a6d961cf039357f061482461e4d2e951ad346satok builder.addTypedWordAndPreviousSuggestions(typedWord, previousSuggestions); 1664fe1a6d961cf039357f061482461e4d2e951ad346satok } 16659fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka } 16667e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka showSuggestions(builder.build(), typedWord); 1667979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 16684a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani 16699fbfd5877305ed19a20663630b498b6b3fdae942satok public void showSuggestions(SuggestedWords suggestedWords, CharSequence typedWord) { 16707e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka setSuggestions(suggestedWords); 16717e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka if (suggestedWords.size() > 0) { 167214e427d5bb13d59d23fb317ef90a6c44ae279425satok if (Utils.shouldBlockedBySafetyNetForAutoCorrection(suggestedWords, mSuggest)) { 167382411d47ba7e8133ed2390c6920945e139a738cesatok mBestWord = typedWord; 167482411d47ba7e8133ed2390c6920945e139a738cesatok } else if (suggestedWords.hasAutoCorrectionWord()) { 16757e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka mBestWord = suggestedWords.getWord(1); 1676923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1677923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = typedWord; 1678923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1679923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1680923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mBestWord = null; 1681923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1682c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShown(isCandidateStripVisible()); 1683923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1684923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1685b5d17e52fcda39d540822e615bfb7ed5074e0034satok private boolean pickDefaultSuggestion(int separatorCode) { 1686923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Complete any pending candidate query first 1687d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka if (mHandler.hasPendingUpdateSuggestions()) { 1688d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 1689923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 1690923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 16916780b898ec2647a21319601a03ae1c393c0e1b29Amith Yamasani if (mBestWord != null && mBestWord.length() > 0) { 16929318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa TextEntryState.acceptedDefault(mWordComposer.getTypedWord(), mBestWord, separatorCode); 16934733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 16941fef530ec7626fa16777f52b48191e61db8f46d4satok commitBestWord(mBestWord); 1695f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard // Add the word to the user unigram dictionary if it's not a known word 1696f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard addToUserUnigramAndBigramDictionaries(mBestWord, 1697f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard UserUnigramDictionary.FREQUENCY_FOR_TYPED); 1698979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return true; 1699923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1700979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return false; 1701923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1702923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1703c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka @Override 1704923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void pickSuggestionManually(int index, CharSequence suggestion) { 17057e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka SuggestedWords suggestions = mCandidateView.getSuggestions(); 170617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mVoiceProxy.flushAndLogAllTextModificationCounters(index, suggestion, 170717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mWordSeparators); 17084f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1709952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa final boolean recorrecting = TextEntryState.isRecorrecting(); 17109351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 17119a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 17129a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.beginBatchEdit(); 17139a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 17141b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (mApplicationSpecifiedCompletionOn && mApplicationSpecifiedCompletions != null 17151b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka && index >= 0 && index < mApplicationSpecifiedCompletions.length) { 1716923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 17179351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index]; 17189351550dc6af7859e5280e16144c9386a37b976dKen Wakasa ic.commitCompletion(completionInfo); 1719923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1720923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCommittedLength = suggestion.length(); 1721923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mCandidateView != null) { 1722923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCandidateView.clear(); 1723923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1724b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 17259a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 17269a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 17279a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1728923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1729923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 17306a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 17316a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani // If this is a punctuation, apply it through the normal key press 173217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (suggestion.length() == 1 && (mSettingsValues.isWordSeparator(suggestion.charAt(0)) 173317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard || mSettingsValues.isSuggestedPunctuation(suggestion.charAt(0)))) { 1734979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Word separators are suggested before the user inputs something. 1735979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // So, LatinImeLogger logs "" as a user's input. 1736979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.logOnManualSuggestion( 17377e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka "", suggestion.toString(), index, suggestions.mWords); 1738863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // Find out whether the previous character is a space. If it is, as a special case 1739863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // for punctuation entered through the suggestion strip, it should be considered 1740863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // a magic space even if it was a normal space. This is meant to help in case the user 1741863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // pressed space on purpose of displaying the suggestion strip punctuation. 174283ffff2a49beeb41874b7cb40819a75001f708e2Ken Wakasa final int rawPrimaryCode = suggestion.charAt(0); 174383ffff2a49beeb41874b7cb40819a75001f708e2Ken Wakasa // Maybe apply the "bidi mirrored" conversions for parentheses 174483ffff2a49beeb41874b7cb40819a75001f708e2Ken Wakasa final LatinKeyboard keyboard = mKeyboardSwitcher.getLatinKeyboard(); 17458da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka final int primaryCode = keyboard.mIsRtlKeyboard 174683ffff2a49beeb41874b7cb40819a75001f708e2Ken Wakasa ? Key.getRtlParenthesisCode(rawPrimaryCode) : rawPrimaryCode; 174783ffff2a49beeb41874b7cb40819a75001f708e2Ken Wakasa 1748eaa10f44a4a0108a90803b1b28238842d3fb5addsatok final CharSequence beforeText = ic != null ? ic.getTextBeforeCursor(1, 0) : ""; 17491f050f634820a1d980e8a91f3a962bcd1fc242e3satok final int toLeft = (ic == null || TextUtils.isEmpty(beforeText)) 17501f050f634820a1d980e8a91f3a962bcd1fc242e3satok ? 0 : beforeText.charAt(0); 17514f3b59711f6985d39e0cc908d2431ae6715d9b26Jean Chalard final boolean oldMagicSpace = mJustAddedMagicSpace; 1752863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard if (Keyboard.CODE_SPACE == toLeft) mJustAddedMagicSpace = true; 1753a96574fdd5e38a237a35b21a2b7c20a29138c648Tadashi G. Takaoka onCodeInput(primaryCode, new int[] { primaryCode }, 1754a96574fdd5e38a237a35b21a2b7c20a29138c648Tadashi G. Takaoka KeyboardActionListener.NOT_A_TOUCH_COORDINATE, 1755a96574fdd5e38a237a35b21a2b7c20a29138c648Tadashi G. Takaoka KeyboardActionListener.NOT_A_TOUCH_COORDINATE); 17564f3b59711f6985d39e0cc908d2431ae6715d9b26Jean Chalard mJustAddedMagicSpace = oldMagicSpace; 17579a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 17589a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 17599a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 17606a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani return; 17616a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 1762f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard if (!mHasUncommittedTypedChars) { 176389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // If we are not composing a word, then it was a suggestion inferred from 176489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // context - no user input. We should reset the word composer. 17659318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.reset(); 176689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 17674733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 17681fef530ec7626fa16777f52b48191e61db8f46d4satok commitBestWord(suggestion); 17699468335a06d2b0e3ef15f4f57f8c1b0857b34ebeAmith Yamasani // Add the word to the auto dictionary if it's not a known word 17700c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani if (index == 0) { 1771f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard addToUserUnigramAndBigramDictionaries(suggestion, 1772f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard UserUnigramDictionary.FREQUENCY_FOR_PICKED); 1773979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } else { 1774bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok addToOnlyBigramDictionary(suggestion, 1); 17750c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani } 17769318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa LatinImeLogger.logOnManualSuggestion(mComposingStringBuilder.toString(), 17779318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa suggestion.toString(), index, suggestions.mWords); 17789318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa TextEntryState.acceptedSuggestion(mComposingStringBuilder.toString(), suggestion); 1779923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Follow it with a space 17800730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard if (mShouldInsertMagicSpace && !recorrecting) { 17810730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard sendMagicSpace(); 1782923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1783979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1784c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // We should show the "Touch again to save" hint if the user pressed the first entry 1785c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // AND either: 17867f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is no dictionary (we know that because we tried to load it => null != mSuggest 1787c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // AND mSuggest.hasMainDictionary() is false) 17887f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is a dictionary and the word is not in it 17897f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // Please note that if mSuggest is null, it means that everything is off: suggestion 17907f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // and correction, so we shouldn't try to show the hint 17917f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // We used to look at mCorrectionMode here, but showing the hint should have nothing 17927f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // to do with the autocorrection setting. 1793bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean showingAddToDictionaryHint = index == 0 && mSuggest != null 1794bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // If there is no dictionary the hint should be shown. 1795c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa && (!mSuggest.hasMainDictionary() 1796bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // If "suggestion" is not in the dictionary, the hint should be shown. 1797bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok || !AutoCorrection.isValidWord( 1798bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok mSuggest.getUnigramDictionaries(), suggestion, true)); 1799b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani 1800952cb7e973bbc4c09728cb5967505f84c80c8bd6Ken Wakasa if (!recorrecting) { 1801b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // Fool the state watcher so that a subsequent backspace will not do a revert, unless 1802b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // we just did a correction, in which case we need to stay in 1803b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani // TextEntryState.State.PICKED_SUGGESTION state. 1804b5d17e52fcda39d540822e615bfb7ed5074e0034satok TextEntryState.typedCharacter((char) Keyboard.CODE_SPACE, true, 1805b5d17e52fcda39d540822e615bfb7ed5074e0034satok WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); 1806777118a40a363ccab69a00016d3156066513cb78Jean Chalard } 1807777118a40a363ccab69a00016d3156066513cb78Jean Chalard if (!showingAddToDictionaryHint) { 1808364da8c618303a7764595d2c15ee034a7671365dKen Wakasa // If we're not showing the "Touch again to save", then show corrections again. 1809979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // In case the cursor position doesn't change, make sure we show the suggestions again. 181041ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard updateBigramPredictions(); 181141ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // Updating the predictions right away may be slow and feel unresponsive on slower 181241ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // terminals. On the other hand if we just postUpdateBigramPredictions() it will 181341ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // take a noticeable delay to update them which may feel uneasy. 1814979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1815b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani if (showingAddToDictionaryHint) { 1816ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka if (mIsUserDictionaryAvaliable) { 1817ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka mCandidateView.showAddToDictionaryHint(suggestion); 1818ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka } else { 1819ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1820ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka } 182166a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani } 18229a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 18239a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.endBatchEdit(); 18249a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1825923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1826a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1827979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 18288558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa * Commits the chosen word to the text field and saves it for later retrieval. 1829979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 18301fef530ec7626fa16777f52b48191e61db8f46d4satok private void commitBestWord(CharSequence bestWord) { 18319351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final KeyboardSwitcher switcher = mKeyboardSwitcher; 1832b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (!switcher.isKeyboardAvailable()) 18331679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka return; 18349351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1835923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 18361fef530ec7626fa16777f52b48191e61db8f46d4satok mVoiceProxy.rememberReplacedWord(bestWord, mSettingsValues.mWordSeparators); 18371fef530ec7626fa16777f52b48191e61db8f46d4satok SuggestedWords suggestedWords = mCandidateView.getSuggestions(); 18381fef530ec7626fa16777f52b48191e61db8f46d4satok ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan( 18391fef530ec7626fa16777f52b48191e61db8f46d4satok this, bestWord, suggestedWords), 1); 1840923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 18419318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mRecorrection.saveRecorrectionSuggestion(mWordComposer, bestWord); 1842f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard mHasUncommittedTypedChars = false; 18431fef530ec7626fa16777f52b48191e61db8f46d4satok mCommittedLength = bestWord.length(); 1844923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1845923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 184689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard private static final WordComposer sEmptyWordComposer = new WordComposer(); 184741ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard public void updateBigramPredictions() { 184889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (mSuggest == null || !isSuggestionsRequested()) 184989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard return; 185089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 185117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (!mSettingsValues.mBigramPredictionEnabled) { 1852cb3320179d39a7983874697a0aa428b127675c9dJean Chalard setPunctuationSuggestions(); 1853cb3320179d39a7983874697a0aa428b127675c9dJean Chalard return; 1854cb3320179d39a7983874697a0aa428b127675c9dJean Chalard } 1855cb3320179d39a7983874697a0aa428b127675c9dJean Chalard 185689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(), 185717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSettingsValues.mWordSeparators); 185889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder( 1859043f7841985916717f4fa821fe3e423daf3ff2f5Jean Chalard mKeyboardSwitcher.getKeyboardView(), sEmptyWordComposer, prevWord, 1860043f7841985916717f4fa821fe3e423daf3ff2f5Jean Chalard mKeyboardSwitcher.getLatinKeyboard().getProximityInfo()); 186189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 186289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (builder.size() > 0) { 186389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Explicitly supply an empty typed word (the no-second-arg version of 186489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // showSuggestions will retrieve the word near the cursor, we don't want that here) 186589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard showSuggestions(builder.build(), ""); 186689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 186789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (!isShowingPunctuationList()) setPunctuationSuggestions(); 186889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 186989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 187089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 18717a8dac55278cedd838be325f56b4c52d973c61f5satok public void setPunctuationSuggestions() { 187217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard setSuggestions(mSettingsValues.mSuggestPuncList); 1873c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShown(isCandidateStripVisible()); 18746a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 18756a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 1876f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard private void addToUserUnigramAndBigramDictionaries(CharSequence suggestion, 1877f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard int frequencyDelta) { 1878979f8690967ff5409fe18f5085858ccdb8e0ccf1satok checkAddToDictionary(suggestion, frequencyDelta, false); 1879979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1880979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1881bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok private void addToOnlyBigramDictionary(CharSequence suggestion, int frequencyDelta) { 1882979f8690967ff5409fe18f5085858ccdb8e0ccf1satok checkAddToDictionary(suggestion, frequencyDelta, true); 1883979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1884979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1885979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 1886f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard * Adds to the UserBigramDictionary and/or UserUnigramDictionary 1887bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok * @param selectedANotTypedWord true if it should be added to bigram dictionary if possible 1888979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 1889979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private void checkAddToDictionary(CharSequence suggestion, int frequencyDelta, 1890bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok boolean selectedANotTypedWord) { 1891979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (suggestion == null || suggestion.length() < 1) return; 1892bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok 18930c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be 18940c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // adding words in situations where the user or application really didn't 18950c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // want corrections enabled or learned. 1896979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (!(mCorrectionMode == Suggest.CORRECTION_FULL 1897979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) { 1898979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return; 1899979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1900bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok 1901f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard final boolean selectedATypedWordAndItsInUserUnigramDic = 1902f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard !selectedANotTypedWord && mUserUnigramDictionary.isValidWord(suggestion); 1903bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean isValidWord = AutoCorrection.isValidWord( 1904bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok mSuggest.getUnigramDictionaries(), suggestion, true); 1905f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard final boolean needsToAddToUserUnigramDictionary = selectedATypedWordAndItsInUserUnigramDic 1906bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok || !isValidWord; 1907f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard if (needsToAddToUserUnigramDictionary) { 1908f4223452119f9ff8b52f026f7ef92d961736dc51Jean Chalard mUserUnigramDictionary.addWord(suggestion.toString(), frequencyDelta); 1909e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka } 1910979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1911e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mUserBigramDictionary != null) { 1912863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // We don't want to register as bigrams words separated by a separator. 1913863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // For example "I will, and you too" : we don't want the pair ("will" "and") to be 1914863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // a bigram. 191540f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final InputConnection ic = getCurrentInputConnection(); 191640f7efc172928bdd6048e91421a766abe5b22996Jean Chalard if (null != ic) { 191740f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final CharSequence prevWord = 191840f7efc172928bdd6048e91421a766abe5b22996Jean Chalard EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators); 191940f7efc172928bdd6048e91421a766abe5b22996Jean Chalard if (!TextUtils.isEmpty(prevWord)) { 192040f7efc172928bdd6048e91421a766abe5b22996Jean Chalard mUserBigramDictionary.addBigrams(prevWord.toString(), suggestion.toString()); 192140f7efc172928bdd6048e91421a766abe5b22996Jean Chalard } 1922979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 192332e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 192432e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 192532e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani 19267a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isCursorTouchingWord() { 19279351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1928923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return false; 1929923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toLeft = ic.getTextBeforeCursor(1, 0); 1930923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence toRight = ic.getTextAfterCursor(1, 0); 1931923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (!TextUtils.isEmpty(toLeft) 193217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isWordSeparator(toLeft.charAt(0)) 193317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isSuggestedPunctuation(toLeft.charAt(0))) { 1934923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1935923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1936a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker if (!TextUtils.isEmpty(toRight) 193717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isWordSeparator(toRight.charAt(0)) 193817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && !mSettingsValues.isSuggestedPunctuation(toRight.charAt(0))) { 1939923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1940923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1941923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 1942923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1943a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 19449351550dc6af7859e5280e16144c9386a37b976dKen Wakasa // "ic" must not null 19459351550dc6af7859e5280e16144c9386a37b976dKen Wakasa private boolean sameAsTextBeforeCursor(final InputConnection ic, CharSequence text) { 1946dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0); 1947dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani return TextUtils.equals(text, beforeText); 1948dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani } 1949dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 19509351550dc6af7859e5280e16144c9386a37b976dKen Wakasa // "ic" must not null 19519351550dc6af7859e5280e16144c9386a37b976dKen Wakasa private void revertLastWord(final InputConnection ic) { 19528558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa if (mHasUncommittedTypedChars || mComposingStringBuilder.length() <= 0) { 1953923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); 19548558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa return; 19558558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa } 19568558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa 19579351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final CharSequence separator = ic.getTextBeforeCursor(1, 0); 195820c4aec82719b5e9b5ddfa990970f19d399aaa2cKen Wakasa ic.deleteSurroundingText(1, 0); 195920c4aec82719b5e9b5ddfa990970f19d399aaa2cKen Wakasa final CharSequence textToTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0); 196020c4aec82719b5e9b5ddfa990970f19d399aaa2cKen Wakasa ic.deleteSurroundingText(mCommittedLength, 0); 19619351550dc6af7859e5280e16144c9386a37b976dKen Wakasa 19629351550dc6af7859e5280e16144c9386a37b976dKen Wakasa // Re-insert "separator" only when the deleted character was word separator and the 19639351550dc6af7859e5280e16144c9386a37b976dKen Wakasa // composing text wasn't equal to the auto-corrected text which can be found before 19649351550dc6af7859e5280e16144c9386a37b976dKen Wakasa // the cursor. 19659351550dc6af7859e5280e16144c9386a37b976dKen Wakasa if (!TextUtils.isEmpty(separator) 19669351550dc6af7859e5280e16144c9386a37b976dKen Wakasa && mSettingsValues.isWordSeparator(separator.charAt(0)) 196720c4aec82719b5e9b5ddfa990970f19d399aaa2cKen Wakasa && !TextUtils.equals(mComposingStringBuilder, textToTheLeft)) { 19688558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa ic.commitText(mComposingStringBuilder, 1); 19698558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa TextEntryState.acceptedTyped(mComposingStringBuilder); 19709351550dc6af7859e5280e16144c9386a37b976dKen Wakasa ic.commitText(separator, 1); 19719351550dc6af7859e5280e16144c9386a37b976dKen Wakasa TextEntryState.typedCharacter(separator.charAt(0), true, 19728558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); 19738558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa // Clear composing text 19748558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa mComposingStringBuilder.setLength(0); 19758558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa } else { 19768558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa mHasUncommittedTypedChars = true; 19778558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa ic.setComposingText(mComposingStringBuilder, 1); 19788558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa TextEntryState.backspace(); 1979923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 19808558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa mHandler.cancelUpdateBigramPredictions(); 19818558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa mHandler.postUpdateSuggestions(); 1982923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1983923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 19849351550dc6af7859e5280e16144c9386a37b976dKen Wakasa // "ic" must not null 19859351550dc6af7859e5280e16144c9386a37b976dKen Wakasa private boolean revertDoubleSpace(final InputConnection ic) { 19864733609947c0ec74e460bd714fffca0518ade93aJean Chalard mHandler.cancelDoubleSpacesTimer(); 19874733609947c0ec74e460bd714fffca0518ade93aJean Chalard // Here we test whether we indeed have a period and a space before us. This should not 19884733609947c0ec74e460bd714fffca0518ade93aJean Chalard // be needed, but it's there just in case something went wrong. 19894733609947c0ec74e460bd714fffca0518ade93aJean Chalard final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0); 19904733609947c0ec74e460bd714fffca0518ade93aJean Chalard if (!". ".equals(textBeforeCursor)) 19914733609947c0ec74e460bd714fffca0518ade93aJean Chalard return false; 19924733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.beginBatchEdit(); 19934733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.deleteSurroundingText(2, 0); 19944733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.commitText(" ", 1); 19954733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.endBatchEdit(); 19964733609947c0ec74e460bd714fffca0518ade93aJean Chalard return true; 19974733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 19984733609947c0ec74e460bd714fffca0518ade93aJean Chalard 1999923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean isWordSeparator(int code) { 200017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard return mSettingsValues.isWordSeparator(code); 2001923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2002923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 20030730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard private void sendMagicSpace() { 2004571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka sendKeyChar((char)Keyboard.CODE_SPACE); 20050730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard mJustAddedMagicSpace = true; 2006b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 2007923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2008923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2009923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean preferCapitalization() { 20109318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa return mWordComposer.isFirstCharCapitalized(); 2011923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2012923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 201388fc9d44186120f9edc5cf7ec0e2af85260fed04satok // Notify that language or mode have been changed and toggleLanguage will update KeyboardID 2014c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // according to new language or mode. 2015c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka public void onRefreshKeyboard() { 201655303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) { 201755303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka // Before Honeycomb, Voice IME is in LatinIME and it changes the current input view, 201855303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka // so that we need to re-create the keyboard input view here. 201955303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka setInputView(mKeyboardSwitcher.onCreateInputView()); 202055303bc63440c6a9547e94b4f3486a00696da9b0Tadashi G. Takaoka } 20214ab730dbd34fad323063f2ffd31ce33de746668dsatok // Reload keyboard because the current language has been changed. 2022255486a5d067469e074f3649b3d2747e7a08aaa2Tadashi G. Takaoka mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettingsValues); 20230ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 202417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 202536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 202636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 20275a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 2028e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka public void onPress(int primaryCode, boolean withSliding) { 2029055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 2030055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka switcher.registerWindowWidth(); 2031055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka if (switcher.isVibrateAndSoundFeedbackRequired()) { 2032cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka vibrate(); 2033cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka playKeyClick(primaryCode); 2034cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka } 20351679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 2036571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { 2037e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka switcher.onPressShift(withSliding); 2038e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { 20396c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onPressSymbol(); 204040a05f62edc6cdedb4365a722b48a72826ef2bf6Tadashi G. Takaoka } else { 20416c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onOtherKeyPressed(); 2042681b102a492b7d5301c1ca87985b4c391eb5eb14Tadashi G. Takaoka } 2043923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2044923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 20455a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 2046e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka public void onRelease(int primaryCode, boolean withSliding) { 20471679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka KeyboardSwitcher switcher = mKeyboardSwitcher; 20483f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani // Reset any drag flags in the keyboard 20491679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); 2050571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { 2051e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka switcher.onReleaseShift(withSliding); 2052e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { 20536c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka switcher.onReleaseSymbol(); 205440a05f62edc6cdedb4365a722b48a72826ef2bf6Tadashi G. Takaoka } 2055923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2056a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2057a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2058123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka // receive ringer mode change and network state change. 2059923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private BroadcastReceiver mReceiver = new BroadcastReceiver() { 2060923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 2061923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onReceive(Context context, Intent intent) { 2062123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final String action = intent.getAction(); 2063123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { 2064123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka updateRingerMode(); 2065123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 2066123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka mSubtypeSwitcher.onNetworkStateChanged(intent); 2067123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } 2068923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2069923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project }; 2070923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2071bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa // update sound effect volume 2072bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa private void updateSoundEffectVolume() { 2073bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa if (mAudioManager == null) { 2074bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 2075bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa if (mAudioManager == null) return; 2076bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa } 2077bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa // This aligns with the current media volume minus 6dB 2078bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa mFxVolume = (float) mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC) 2079bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa / (float) mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) / 4.0f; 2080bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa } 2081bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa 2082923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // update flags for silent mode 2083923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void updateRingerMode() { 2084923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 2085923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 2086bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa if (mAudioManager == null) return; 2087923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2088bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa mSilentModeOn = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL); 2089923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2090923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2091923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void playKeyClick(int primaryCode) { 2092923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // if mAudioManager is null, we don't have the ringer state yet 2093923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // mAudioManager will be set by updateRingerMode 2094923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mAudioManager == null) { 2095c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka if (mKeyboardSwitcher.getKeyboardView() != null) { 2096923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateRingerMode(); 2097923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2098923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 209917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (isSoundOn()) { 2100923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int sound = AudioManager.FX_KEYPRESS_STANDARD; 2101923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 2102571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_DELETE: 2103923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_DELETE; 2104923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 2105571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_ENTER: 2106923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_RETURN; 2107923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 2108571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_SPACE: 2109923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project sound = AudioManager.FX_KEYPRESS_SPACEBAR; 2110923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project break; 2111923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2112bf7dd47329c23c846912b268d15e8083ffdaabdeKen Wakasa mAudioManager.playSoundEffect(sound, mFxVolume); 2113923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2114923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2115923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2116409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void vibrate() { 211717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (!mSettingsValues.mVibrateOn) { 2118923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 2119923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2120c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 21211679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka if (inputView != null) { 21221679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka inputView.performHapticFeedback( 2123979f8690967ff5409fe18f5085858ccdb8e0ccf1satok HapticFeedbackConstants.KEYBOARD_TAP, 212466a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); 2125923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2126923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2127923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 212871c353aa875f5237b1dce4e18bd4fe86ce28b58eTadashi G. Takaoka public WordComposer getCurrentWord() { 21299318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa return mWordComposer; 21306516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani } 21316516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani 213217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard boolean isSoundOn() { 213317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard return mSettingsValues.mSoundOn && !mSilentModeOn; 2134979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2135979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2136e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private void updateCorrectionMode() { 21379f67e12a0e3f77985fb8bafe0db4c00e32317b9asatok // TODO: cleanup messy flags 2138f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled 2139c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa && !mInputTypeNoAutoCorrect; 214017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mCorrectionMode = (shouldAutoCorrect && mSettingsValues.mAutoCorrectEnabled) 2141e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani ? Suggest.CORRECTION_FULL 214217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard : (shouldAutoCorrect ? Suggest.CORRECTION_BASIC : Suggest.CORRECTION_NONE); 214317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mCorrectionMode = (mSettingsValues.mBigramSuggestionEnabled && shouldAutoCorrect 214417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard && mSettingsValues.mAutoCorrectEnabled) 2145979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ? Suggest.CORRECTION_FULL_BIGRAM : mCorrectionMode; 2146e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani if (mSuggest != null) { 2147e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani mSuggest.setCorrectionMode(mCorrectionMode); 2148e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 2149e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 2150e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani 21510ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private void updateAutoTextEnabled() { 215232e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani if (mSuggest == null) return; 2153f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard // We want to use autotext if the settings are asking for auto corrections, and if 2154f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard // the input language is the same as the system language (because autotext will only 2155f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard // work in the system language so if we are entering text in a different language we 2156f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard // do not want it on). 2157f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard // We used to look at the "quick fixes" option instead of mAutoCorrectEnabled, but 2158f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard // this option was redundant and confusing and therefore removed. 2159f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard mSuggest.setQuickFixesEnabled(mSettingsValues.mAutoCorrectEnabled 21604ab730dbd34fad323063f2ffd31ce33de746668dsatok && SubtypeSwitcher.getInstance().isSystemLanguageSameAsInputLanguage()); 216132e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 216232e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani 216317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard private void updateSuggestionVisibility(final SharedPreferences prefs, final Resources res) { 21647599cfea4a2d56f4779452ec8e8742f7b9629cc0satok final String suggestionVisiblityStr = prefs.getString( 21659502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Settings.PREF_SHOW_SUGGESTIONS_SETTING, 2166458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa res.getString(R.string.prefs_suggestion_visibility_default_value)); 21677599cfea4a2d56f4779452ec8e8742f7b9629cc0satok for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) { 2168458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa if (suggestionVisiblityStr.equals(res.getString(visibility))) { 21697599cfea4a2d56f4779452ec8e8742f7b9629cc0satok mSuggestionVisibility = visibility; 21707599cfea4a2d56f4779452ec8e8742f7b9629cc0satok break; 21717599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 21727599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 21737599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 21747599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 2175466741d8a78965b8509bf527344f289e50873092Mike LeBeau protected void launchSettings() { 2176cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa launchSettingsClass(Settings.class); 2177466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 2178466741d8a78965b8509bf527344f289e50873092Mike LeBeau 2179bf96661d33d0126adb60a48880ceba1ff055d4a4satok public void launchDebugSettings() { 2180cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa launchSettingsClass(DebugSettings.class); 2181bf96661d33d0126adb60a48880ceba1ff055d4a4satok } 2182bf96661d33d0126adb60a48880ceba1ff055d4a4satok 2183cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa protected void launchSettingsClass(Class<? extends PreferenceActivity> settingsClass) { 2184923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project handleClose(); 2185923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Intent intent = new Intent(); 2186466741d8a78965b8509bf527344f289e50873092Mike LeBeau intent.setClass(LatinIME.this, settingsClass); 2187923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2188923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project startActivity(intent); 2189923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2190923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 21912fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showSubtypeSelectorAndSettings() { 219285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 219385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 219485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka // TODO: Should use new string "Select active input modes". 219585996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.language_selection_title), 219685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 219785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 219885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 21992fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka @Override 22002fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka public void onClick(DialogInterface di, int position) { 22012fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka di.dismiss(); 22022fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka switch (position) { 220385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 22042cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok Intent intent = CompatUtils.getInputLanguageSelectionIntent( 22052cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok mInputMethodId, Intent.FLAG_ACTIVITY_NEW_TASK 22062fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 22072fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_CLEAR_TOP); 22082fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka startActivity(intent); 22092fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2210aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa case 1: 2211aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa launchSettings(); 2212aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa break; 22132fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 22142fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 221585996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 2216bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka final AlertDialog.Builder builder = new AlertDialog.Builder(this) 2217bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setItems(items, listener) 2218bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setTitle(title); 2219bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka showOptionDialogInternal(builder.create()); 22202fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 2221923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 22222fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showOptionsMenu() { 222385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 222485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 222585996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.selectInputMethod), 222685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 222785996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 222885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 22295a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 2230923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onClick(DialogInterface di, int position) { 2231923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project di.dismiss(); 2232923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (position) { 223385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 2234ea55bf5df7d26d12b36c47141bfbac5730c3929aTadashi G. Takaoka mImm.showInputMethodPicker(); 22352fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 223685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 1: 2237ea55bf5df7d26d12b36c47141bfbac5730c3929aTadashi G. Takaoka launchSettings(); 22382fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2239923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2240923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 224185996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 2242bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka final AlertDialog.Builder builder = new AlertDialog.Builder(this) 2243bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setItems(items, listener) 2244bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setTitle(title); 2245bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka showOptionDialogInternal(builder.create()); 2246923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2247923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 22487e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 22497e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 2250923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.dump(fd, fout, args); 2251a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2252923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final Printer p = new PrintWriterPrinter(fout); 2253923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println("LatinIME state :"); 2254923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" Keyboard mode = " + mKeyboardSwitcher.getKeyboardMode()); 22559318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa p.println(" mComposingStringBuilder=" + mComposingStringBuilder.toString()); 22569fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka p.println(" mIsSuggestionsRequested=" + mIsSettingsSuggestionStripOn); 2257923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mCorrectionMode=" + mCorrectionMode); 2258f108bf8fe924722ac6fc451f0235eb85a60f459dJean Chalard p.println(" mHasUncommittedTypedChars=" + mHasUncommittedTypedChars); 225917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mAutoCorrectEnabled=" + mSettingsValues.mAutoCorrectEnabled); 22600730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard p.println(" mShouldInsertMagicSpace=" + mShouldInsertMagicSpace); 22611b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka p.println(" mApplicationSpecifiedCompletionOn=" + mApplicationSpecifiedCompletionOn); 2262923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" TextEntryState.state=" + TextEntryState.getState()); 226317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mSoundOn=" + mSettingsValues.mSoundOn); 226417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mVibrateOn=" + mSettingsValues.mVibrateOn); 2265240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard p.println(" mKeyPreviewPopupOn=" + mSettingsValues.mKeyPreviewPopupOn); 2266923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 22676e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani 2268923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Characters per second measurement 2269a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2270923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastCpsTime; 2271923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int CPS_BUFFER_SIZE = 16; 2272923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long[] mCpsIntervals = new long[CPS_BUFFER_SIZE]; 2273923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mCpsIndex; 2274a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2275923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void measureCps() { 2276923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long now = System.currentTimeMillis(); 2277923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mLastCpsTime == 0) mLastCpsTime = now - 100; // Initial 2278923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCpsIntervals[mCpsIndex] = now - mLastCpsTime; 2279923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastCpsTime = now; 2280923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCpsIndex = (mCpsIndex + 1) % CPS_BUFFER_SIZE; 2281923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project long total = 0; 2282923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project for (int i = 0; i < CPS_BUFFER_SIZE; i++) total += mCpsIntervals[i]; 2283923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total)); 2284923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2285923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 2286