LatinIME.java revision 78e3977e90a9946a057dfb628f99683e386015bd
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 191cb08acaf3b4d58cbf4cb65f9fc3990b39e33f00Tadashi G. Takaokaimport static com.android.inputmethod.latin.Constants.ImeOption.FORCE_ASCII; 201cb08acaf3b4d58cbf4cb65f9fc3990b39e33f00Tadashi G. Takaokaimport static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE; 211cb08acaf3b4d58cbf4cb65f9fc3990b39e33f00Tadashi G. Takaokaimport static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE_COMPAT; 221cb08acaf3b4d58cbf4cb65f9fc3990b39e33f00Tadashi G. Takaoka 23923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.app.AlertDialog; 24923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.BroadcastReceiver; 25923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Context; 26923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.DialogInterface; 27923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Intent; 28923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.IntentFilter; 29923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.SharedPreferences; 30923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.res.Configuration; 3136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasaniimport android.content.res.Resources; 32c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaokaimport android.graphics.Rect; 33923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.inputmethodservice.InputMethodService; 34923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.media.AudioManager; 35123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaokaimport android.net.ConnectivityManager; 36923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Debug; 3781d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaokaimport android.os.IBinder; 38923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Message; 39923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.SystemClock; 40bf96661d33d0126adb60a48880ceba1ff055d4a4satokimport android.preference.PreferenceActivity; 41923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.preference.PreferenceManager; 42e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaokaimport android.text.InputType; 43923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.text.TextUtils; 44923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Log; 45923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.PrintWriterPrinter; 46923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Printer; 47923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.View; 488e09172df1bb176cc899940862c56bed9b9aec4esatokimport android.view.ViewGroup; 49c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaokaimport android.view.ViewGroup.LayoutParams; 50cc8c8b99bd0463f5977dea82f5e2379ea1dd4e73Tadashi G. Takaokaimport android.view.ViewParent; 5113d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaokaimport android.view.Window; 5213d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaokaimport android.view.WindowManager; 53923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.CompletionInfo; 5496fdc4dd8426a078500ce1d8a104bde7201bf9b5Ken Wakasaimport android.view.inputmethod.CorrectionInfo; 55923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.EditorInfo; 56923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.InputConnection; 579cc2c94c8b4bfd4e00e5d3478b9f6e520e791bc5Tadashi G. Takaokaimport android.view.inputmethod.InputMethodSubtype; 58c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka 595ac4638f999db4fea8a9e24171dbceb640a10858Alan Viveretteimport com.android.inputmethod.accessibility.AccessibilityUtils; 608d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanvimport com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; 61c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.CompatUtils; 62c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.compat.InputMethodManagerCompatWrapper; 631fef530ec7626fa16777f52b48191e61db8f46d4satokimport com.android.inputmethod.compat.SuggestionSpanUtils; 64c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.Keyboard; 65c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardActionListener; 666b7100fecaaaf0e8e42c4d2ccebac165e89e79bfTadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardId; 67c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardSwitcher; 68f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardView; 69c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaokaimport com.android.inputmethod.keyboard.LatinKeyboardView; 7016c6f355700ee5cdaa029f4a25b8b3d40718e6abTadashi G. Takaokaimport com.android.inputmethod.latin.LocaleUtils.RunInLocale; 71c166697e3f5ec600089987dbbff0be7f3e308565Ken Wakasaimport com.android.inputmethod.latin.define.ProductionFlag; 728c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaokaimport com.android.inputmethod.latin.suggestions.SuggestionsView; 73923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 74466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.FileDescriptor; 75466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.PrintWriter; 764ee186920e642ae8ebe0b6c97dfdceb0ad2fdeefJean Chalardimport java.util.ArrayList; 77466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.Locale; 78466741d8a78965b8509bf527344f289e50873092Mike LeBeau 79923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/** 80923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Input method implementation for Qwerty'ish keyboard. 81923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 8213d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaokapublic class LatinIME extends InputMethodService implements KeyboardActionListener, 83913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka SuggestionsView.Listener { 848efc0addce3cd1a32618bf18bafabaaca2b498b0Tadashi G. Takaoka private static final String TAG = LatinIME.class.getSimpleName(); 85409220583333bdf06290dd9fd42f91b5c0d1b11asatok private static final boolean TRACE = false; 869e2d810dc524380ca1db6b384cfb00b4401585e5Tadashi G. Takaoka private static boolean DEBUG; 87a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 889e347d3d448e48229c46aad394ec9bd60cd5807bsatok private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100; 89fd0bd57deb53c4cce32810a61133fa44b45dbb7bKen Wakasa 90923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // How many continuous deletes at which to start deleting at a higher speed. 91923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int DELETE_ACCELERATE_AT = 20; 92923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Key events coming any faster than this are long-presses. 93d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani private static final int QUICK_PRESS = 200; 94a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 9559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private static final int PENDING_IMS_CALLBACK_DURATION = 800; 96f4cf5b9952ae331806bf656a6f977a5ece47fe80satok // TODO: remove this 97f4cf5b9952ae331806bf656a6f977a5ece47fe80satok private static final boolean WORKAROUND_USE_LAST_BACKING_HEIGHT_WHEN_NOT_READY = true; 98f4cf5b9952ae331806bf656a6f977a5ece47fe80satok private static int sLastBackingHeight = 0; 99055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 100cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard /** 101cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard * The name of the scheme used by the Package Manager to warn of a new package installation, 102cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard * replacement or removal. 103cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard */ 104cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard private static final String SCHEME_PACKAGE = "package"; 105cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 10618222f8c863e509538857b1fafca9c696fae2f55Tom Ouyang /** Whether to use the binary version of the contacts dictionary */ 10718222f8c863e509538857b1fafca9c696fae2f55Tom Ouyang public static final boolean USE_BINARY_CONTACTS_DICTIONARY = true; 10818222f8c863e509538857b1fafca9c696fae2f55Tom Ouyang 109f6adff6227a15af105dbf39c57213a24bf16780bTom Ouyang /** Whether to use the binary version of the user dictionary */ 110f6adff6227a15af105dbf39c57213a24bf16780bTom Ouyang public static final boolean USE_BINARY_USER_DICTIONARY = true; 111f6adff6227a15af105dbf39c57213a24bf16780bTom Ouyang 1120fe3611bee5095e7bd0fff2d0fdf8d5a13379132Jean Chalard // TODO: migrate this to SettingsValues 1137599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private int mSuggestionVisibility; 1147599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_VALUE 1157599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_value; 1167599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 1177599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_show_only_portrait_value; 1187599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int SUGGESTION_VISIBILILTY_HIDE_VALUE 1197599cfea4a2d56f4779452ec8e8742f7b9629cc0satok = R.string.prefs_suggestion_visibility_hide_value; 1207599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 1217599cfea4a2d56f4779452ec8e8742f7b9629cc0satok private static final int[] SUGGESTION_VISIBILITY_VALUE_ARRAY = new int[] { 1227599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_VALUE, 1237599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE, 1247599cfea4a2d56f4779452ec8e8742f7b9629cc0satok SUGGESTION_VISIBILILTY_HIDE_VALUE 1257599cfea4a2d56f4779452ec8e8742f7b9629cc0satok }; 1267599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 127fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard private static final int SPACE_STATE_NONE = 0; 128120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Double space: the state where the user pressed space twice quickly, which LatinIME 129120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // resolved as period-space. Undoing this converts the period to a space. 130fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard private static final int SPACE_STATE_DOUBLE = 1; 131b141c9cd3f6785bc0a4e1f5385f4e6e2e17955bbJean Chalard // Swap punctuation: the state where a weak space and a punctuation from the suggestion strip 132b141c9cd3f6785bc0a4e1f5385f4e6e2e17955bbJean Chalard // have just been swapped. Undoing this swaps them back; the space is still considered weak. 133120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private static final int SPACE_STATE_SWAP_PUNCTUATION = 2; 134fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // Weak space: a space that should be swapped only by suggestion strip punctuation. Weak 135fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // spaces happen when the user presses space, accepting the current suggestion (whether 136fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // it's an auto-correction or not). 137fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard private static final int SPACE_STATE_WEAK = 3; 138fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // Phantom space: a not-yet-inserted space that should get inserted on the next input, 139fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // character provided it's not a separator. If it's a separator, the phantom space is dropped. 140fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // Phantom spaces happen when a user chooses a word from the suggestion strip. 141fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard private static final int SPACE_STATE_PHANTOM = 4; 142120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 143120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Current space state of the input method. This can be any of the above constants. 144120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private int mSpaceState; 145126698fdd256a2e3734634d3b923cabd800064baJean Chalard 1467a16a061e622539e54d7d649dcb8d4965aea575aJean Chalard private SettingsValues mSettingsValues; 14780b66bb166f7f45adfcadcb84788477df9930828Jean Chalard private InputAttributes mInputAttributes; 14817c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 149d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka private View mExtractArea; 150abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka private View mKeyPreviewBackingView; 151913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka private View mSuggestionsContainer; 152913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka private SuggestionsView mSuggestionsView; 153816a8a0fd85ca0327436f8bd1cfa6928600ebc5dJean Chalard /* package for tests */ Suggest mSuggest; 1541b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka private CompletionInfo[] mApplicationSpecifiedCompletions; 155a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 156610f1dc8553cf2ed97e763a06a19380c4a6cd636satok private InputMethodManagerCompatWrapper mImm; 1572fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private Resources mResources; 1582fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private SharedPreferences mPrefs; 159109728193e45262099cbf88d8d6fcc4ed05240caJean Chalard /* package for tests */ final KeyboardSwitcher mKeyboardSwitcher; 16089ffb212b469531db4a616afb9bb7ba6d2a56b50Jean Chalard private final SubtypeSwitcher mSubtypeSwitcher; 16181d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka private boolean mShouldSwitchToLastSubtype = true; 162a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1636a7019ff5db19b1e3f8d7afbba71af813cab9a37Tadashi G. Takaoka private boolean mIsMainDictionaryAvailable; 164f6adff6227a15af105dbf39c57213a24bf16780bTom Ouyang // TODO: revert this back to the concrete class after transition. 165f6adff6227a15af105dbf39c57213a24bf16780bTom Ouyang private Dictionary mUserDictionary; 1669ffb94fa1318f354692fab7abf4775fa14397a96Jean Chalard private UserHistoryDictionary mUserHistoryDictionary; 16788562bec54658840dcce352127bdc15705c20a89Jean Chalard private boolean mIsUserDictionaryAvailable; 16836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 1692692a8700737d8eed268039aa27b22a31669da08Jean Chalard private LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; 1709318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa private WordComposer mWordComposer = new WordComposer(); 171409220583333bdf06290dd9fd42f91b5c0d1b11asatok 17279efbed76f638be298493107fa2d0cd1b5eb529esatok private int mCorrectionMode; 17377da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard 174979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Keep track of the last selection range to decide if we need to show word alternatives 17577da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard private static final int NOT_A_CURSOR_POSITION = -1; 17677da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard private int mLastSelectionStart = NOT_A_CURSOR_POSITION; 17777da3d5a3baab0a88f78db5800bb9ede0b39ff60Jean Chalard private int mLastSelectionEnd = NOT_A_CURSOR_POSITION; 178979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1794733609947c0ec74e460bd714fffca0518ade93aJean Chalard // Whether we are expecting an onUpdateSelection event to fire. If it does when we don't 1804733609947c0ec74e460bd714fffca0518ade93aJean Chalard // "expect" it, it means the user actually moved the cursor. 1814733609947c0ec74e460bd714fffca0518ade93aJean Chalard private boolean mExpectingUpdateSelection; 182923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mDeleteCount; 183923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private long mLastKeyTime; 184a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 185564496bad6207f02e7a653872213bc5954e84ce4Jean Chalard private AudioAndHapticFeedbackManager mFeedbackManager; 18628f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa 18738f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka // Member variables for remembering the current device orientation. 18838f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka private int mDisplayOrientation; 18938f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 190cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Object for reacting to adding/removing a dictionary pack. 191cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard private BroadcastReceiver mDictionaryPackInstallReceiver = 192cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard new DictionaryPackInstallBroadcastReceiver(this); 193cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 194dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani // Keeps track of most recently inserted text (multi-character key) for reverting 195dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani private CharSequence mEnteredText; 196dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 19770852c91dc7209d0aaa875a2cb0f79739c7398e6Jean Chalard private boolean mIsAutoCorrectionIndicatorOn; 198604d80c67185954d4691ac775be59c499eee3b1csatok 19913d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka private AlertDialog mOptionsDialog; 20013d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka 2014f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public final UIHandler mHandler = new UIHandler(this); 202d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 2034f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public static class UIHandler extends StaticInnerHandlerWrapper<LatinIME> { 20445f45a4fdb16d0fa44b4a34b880e5fabb41c1492Jean Chalard private static final int MSG_UPDATE_SHIFT_STATE = 1; 2054c0c638a189c1073b1fb6e43fe5fddb6f9932038Tadashi G. Takaoka private static final int MSG_SPACE_TYPED = 4; 2064c0c638a189c1073b1fb6e43fe5fddb6f9932038Tadashi G. Takaoka private static final int MSG_SET_BIGRAM_PREDICTIONS = 5; 2074c0c638a189c1073b1fb6e43fe5fddb6f9932038Tadashi G. Takaoka private static final int MSG_PENDING_IMS_CALLBACK = 6; 2084c0c638a189c1073b1fb6e43fe5fddb6f9932038Tadashi G. Takaoka private static final int MSG_UPDATE_SUGGESTIONS = 7; 2094c0c638a189c1073b1fb6e43fe5fddb6f9932038Tadashi G. Takaoka 21010dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private int mDelayUpdateSuggestions; 21110dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private int mDelayUpdateShiftState; 21210dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka private long mDoubleSpacesTurnIntoPeriodTimeout; 21338f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 2144f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa public UIHandler(LatinIME outerInstance) { 2154f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa super(outerInstance); 21610dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka } 217175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka 21810dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka public void onCreate() { 21910dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka final Resources res = getOuterInstance().getResources(); 220175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDelayUpdateSuggestions = 221175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka res.getInteger(R.integer.config_delay_update_suggestions); 222175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDelayUpdateShiftState = 223175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka res.getInteger(R.integer.config_delay_update_shift_state); 224175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka mDoubleSpacesTurnIntoPeriodTimeout = res.getInteger( 225175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka R.integer.config_double_spaces_turn_into_period_timeout); 2264f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa } 2274f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa 228923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 229923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void handleMessage(Message msg) { 2304f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final LatinIME latinIme = getOuterInstance(); 2314f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa final KeyboardSwitcher switcher = latinIme.mKeyboardSwitcher; 232923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (msg.what) { 233d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SUGGESTIONS: 2344f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.updateSuggestions(); 235d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 236d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka case MSG_UPDATE_SHIFT_STATE: 237de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka switcher.updateShiftState(); 238d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka break; 239cb3320179d39a7983874697a0aa428b127675c9dJean Chalard case MSG_SET_BIGRAM_PREDICTIONS: 2404f0d290c5d112ebac434bd8de4635f7d42ea2df0Ken Wakasa latinIme.updateBigramPredictions(); 24189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard break; 242923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 243923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 244d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 245d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void postUpdateSuggestions() { 246d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 247175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS), mDelayUpdateSuggestions); 248d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 249d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 250d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateSuggestions() { 251d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SUGGESTIONS); 252d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 253d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 254d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public boolean hasPendingUpdateSuggestions() { 255d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka return hasMessages(MSG_UPDATE_SUGGESTIONS); 256d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 257d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 258beb08b398fa73a26f2d42d6feec87e34a96ca2d9Tadashi G. Takaoka public void postUpdateShiftState() { 259d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 260175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE), mDelayUpdateShiftState); 261d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 262d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 263d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka public void cancelUpdateShiftState() { 264d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka removeMessages(MSG_UPDATE_SHIFT_STATE); 265d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka } 266d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka 267cb3320179d39a7983874697a0aa428b127675c9dJean Chalard public void postUpdateBigramPredictions() { 268cb3320179d39a7983874697a0aa428b127675c9dJean Chalard removeMessages(MSG_SET_BIGRAM_PREDICTIONS); 269175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS), mDelayUpdateSuggestions); 27089bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 27189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 272cb3320179d39a7983874697a0aa428b127675c9dJean Chalard public void cancelUpdateBigramPredictions() { 273cb3320179d39a7983874697a0aa428b127675c9dJean Chalard removeMessages(MSG_SET_BIGRAM_PREDICTIONS); 27489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 27589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 276fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public void startDoubleSpacesTimer() { 277fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka removeMessages(MSG_SPACE_TYPED); 278175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED), mDoubleSpacesTurnIntoPeriodTimeout); 279fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 280fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 281fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public void cancelDoubleSpacesTimer() { 282fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka removeMessages(MSG_SPACE_TYPED); 283fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 284fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka 285fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka public boolean isAcceptingDoubleSpaces() { 286fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka return hasMessages(MSG_SPACE_TYPED); 287fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka } 28838f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 28959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Working variables for the following methods. 29059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mIsOrientationChanging; 2915fd11a7f3367d51cea8dc83fb9675c93d82a2e4eJean Chalard private boolean mPendingSuccessiveImsCallback; 29259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mHasPendingStartInput; 29359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mHasPendingFinishInputView; 29459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private boolean mHasPendingFinishInput; 295e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka private EditorInfo mAppliedEditorInfo; 29659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 29759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void startOrientationChanging() { 298dd25e4fa2c7dd1e32a9e6f5fd21f54214919ef20Tadashi G. Takaoka removeMessages(MSG_PENDING_IMS_CALLBACK); 299dd25e4fa2c7dd1e32a9e6f5fd21f54214919ef20Tadashi G. Takaoka resetPendingImsCallback(); 30059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mIsOrientationChanging = true; 301055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 302f2c9a88887a303f3df8bee60788870946dfa55f7Tadashi G. Takaoka if (latinIme.isInputViewShown()) { 303f2c9a88887a303f3df8bee60788870946dfa55f7Tadashi G. Takaoka latinIme.mKeyboardSwitcher.saveKeyboardState(); 304f2c9a88887a303f3df8bee60788870946dfa55f7Tadashi G. Takaoka } 30559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 30659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 30759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void resetPendingImsCallback() { 30859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInputView = false; 30959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInput = false; 31059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingStartInput = false; 31159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 31259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 313e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka private void executePendingImsCallback(LatinIME latinIme, EditorInfo editorInfo, 31459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka boolean restarting) { 31559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mHasPendingFinishInputView) 31659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputViewInternal(mHasPendingFinishInput); 31759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mHasPendingFinishInput) 31859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputInternal(); 31959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mHasPendingStartInput) 320e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka latinIme.onStartInputInternal(editorInfo, restarting); 32159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka resetPendingImsCallback(); 32259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 32359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 324e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka public void onStartInput(EditorInfo editorInfo, boolean restarting) { 32559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { 32659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Typically this is the second onStartInput after orientation changed. 32759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingStartInput = true; 32859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } else { 32959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (mIsOrientationChanging && restarting) { 33059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // This is the first onStartInput after orientation changed. 33159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mIsOrientationChanging = false; 3325fd11a7f3367d51cea8dc83fb9675c93d82a2e4eJean Chalard mPendingSuccessiveImsCallback = true; 33359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 33459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 335e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka executePendingImsCallback(latinIme, editorInfo, restarting); 336e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka latinIme.onStartInputInternal(editorInfo, restarting); 337055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 338055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 339055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 340e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka public void onStartInputView(EditorInfo editorInfo, boolean restarting) { 3416b7100fecaaaf0e8e42c4d2ccebac165e89e79bfTadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK) 3426b7100fecaaaf0e8e42c4d2ccebac165e89e79bfTadashi G. Takaoka && KeyboardId.equivalentEditorInfoForKeyboard(editorInfo, mAppliedEditorInfo)) { 343e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka // Typically this is the second onStartInputView after orientation changed. 344e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka resetPendingImsCallback(); 345e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka } else { 3465fd11a7f3367d51cea8dc83fb9675c93d82a2e4eJean Chalard if (mPendingSuccessiveImsCallback) { 347e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka // This is the first onStartInputView after orientation changed. 3485fd11a7f3367d51cea8dc83fb9675c93d82a2e4eJean Chalard mPendingSuccessiveImsCallback = false; 349e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka resetPendingImsCallback(); 350e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka sendMessageDelayed(obtainMessage(MSG_PENDING_IMS_CALLBACK), 351e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka PENDING_IMS_CALLBACK_DURATION); 352e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka } 353e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 354e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka executePendingImsCallback(latinIme, editorInfo, restarting); 355e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka latinIme.onStartInputViewInternal(editorInfo, restarting); 356e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mAppliedEditorInfo = editorInfo; 357e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka } 35859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 35959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 36059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInputView(boolean finishingInput) { 36159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { 36259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Typically this is the first onFinishInputView after orientation changed. 36359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInputView = true; 36459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } else { 36559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 36659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputViewInternal(finishingInput); 367e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mAppliedEditorInfo = null; 36838f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 36938f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 370ffd156c77e93a54b704780b46886ba597d1c77cbTadashi G. Takaoka 37159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInput() { 37259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { 37359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka // Typically this is the first onFinishInput after orientation changed. 37459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHasPendingFinishInput = true; 37559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } else { 37659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka final LatinIME latinIme = getOuterInstance(); 37759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka executePendingImsCallback(latinIme, null, false); 37859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka latinIme.onFinishInputInternal(); 379ffd156c77e93a54b704780b46886ba597d1c77cbTadashi G. Takaoka } 380ffd156c77e93a54b704780b46886ba597d1c77cbTadashi G. Takaoka } 38138f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka } 38238f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 38389ffb212b469531db4a616afb9bb7ba6d2a56b50Jean Chalard public LatinIME() { 38489ffb212b469531db4a616afb9bb7ba6d2a56b50Jean Chalard super(); 38589ffb212b469531db4a616afb9bb7ba6d2a56b50Jean Chalard mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 38689ffb212b469531db4a616afb9bb7ba6d2a56b50Jean Chalard mKeyboardSwitcher = KeyboardSwitcher.getInstance(); 38789ffb212b469531db4a616afb9bb7ba6d2a56b50Jean Chalard } 38889ffb212b469531db4a616afb9bb7ba6d2a56b50Jean Chalard 3897e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 3907e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka public void onCreate() { 39127d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 39227d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa mPrefs = prefs; 39327d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa LatinImeLogger.init(this, prefs); 394c166697e3f5ec600089987dbbff0be7f3e308565Ken Wakasa if (ProductionFlag.IS_EXPERIMENTAL) { 395c166697e3f5ec600089987dbbff0be7f3e308565Ken Wakasa ResearchLogger.init(this, prefs); 396c166697e3f5ec600089987dbbff0be7f3e308565Ken Wakasa } 397bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka InputMethodManagerCompatWrapper.init(this); 398ef5dfc480c7a3e3e34a20b7aacc731942e7a0578Tadashi G. Takaoka SubtypeSwitcher.init(this); 39927d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa KeyboardSwitcher.init(this, prefs); 4002ac5988f84b5c38d313951a3d7faddebf5f25e04Tadashi G. Takaoka AccessibilityUtils.init(this); 401363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 402923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onCreate(); 403363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 404bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka mImm = InputMethodManagerCompatWrapper.getInstance(); 40510dff76856a98b6eec86a53d3d07fdc9708037b7Tadashi G. Takaoka mHandler.onCreate(); 4069e2d810dc524380ca1db6b384cfb00b4401585e5Tadashi G. Takaoka DEBUG = LatinImeLogger.sDBG; 407363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka 408363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka final Resources res = getResources(); 409363cd6ef0f8f8af41a01964a2f0e800f9305d3a2Tadashi G. Takaoka mResources = res; 410fd7d814c81132bdd59146a39dd668532f9514cd1Jean Chalard 41128f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa loadSettings(); 41228f36d68afe8d323d1032d0e03fe3013449e21feKen Wakasa 413f5a0bd2c28fd9ec1de8fe49196e7f7ae38566f90Tadashi G. Takaoka ImfUtils.setAdditionalInputMethodSubtypes(this, mSettingsValues.getAdditionalSubtypes()); 414f6972561fcb45310f18230ce217f0c6bb57e7eeeTadashi G. Takaoka 415dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard // TODO: remove the following when it's not needed by updateCorrectionMode() any more 416644c8b7c96627199c13297082e4566adae159bf3Jean Chalard mInputAttributes = new InputAttributes(null, false /* isFullscreenMode */); 4173fe263fac6375836c48ce71da29f098b66eb4f11Jean Chalard updateCorrectionMode(); 4183fe263fac6375836c48ce71da29f098b66eb4f11Jean Chalard 4199502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Utils.GCUtils.getInstance().reset(); 420979f8690967ff5409fe18f5085858ccdb8e0ccf1satok boolean tryGC = true; 4219502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { 422979f8690967ff5409fe18f5085858ccdb8e0ccf1satok try { 4230ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 424979f8690967ff5409fe18f5085858ccdb8e0ccf1satok tryGC = false; 425979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } catch (OutOfMemoryError e) { 4269502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka tryGC = Utils.GCUtils.getInstance().tryGCOrWait("InitSuggest", e); 427979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 428979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 429979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 430f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka mDisplayOrientation = res.getConfiguration().orientation; 431b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 432cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Register to receive ringer mode change and network state change. 433cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard // Also receive installation and removal of a dictionary pack. 434123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final IntentFilter filter = new IntentFilter(); 435123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 43621af2f40c59de3ea5ec183aa278406bf28d5e3bdJean Chalard filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); 437923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project registerReceiver(mReceiver, filter); 438cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 439cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard final IntentFilter packageFilter = new IntentFilter(); 440cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 441cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 442cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard packageFilter.addDataScheme(SCHEME_PACKAGE); 443cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard registerReceiver(mDictionaryPackInstallReceiver, packageFilter); 444646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard 445646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard final IntentFilter newDictFilter = new IntentFilter(); 446646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard newDictFilter.addAction( 447646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard DictionaryPackInstallBroadcastReceiver.NEW_DICTIONARY_INTENT_ACTION); 448646d950ed8d2b2555df92855e18b350fd7761b21Jean Chalard registerReceiver(mDictionaryPackInstallReceiver, newDictFilter); 449923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 45036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 45117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard // Has to be package-visible for unit tests 45217c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard /* package */ void loadSettings() { 45317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this); 45416c6f355700ee5cdaa029f4a25b8b3d40718e6abTadashi G. Takaoka final RunInLocale<SettingsValues> job = new RunInLocale<SettingsValues>() { 45516c6f355700ee5cdaa029f4a25b8b3d40718e6abTadashi G. Takaoka @Override 45616c6f355700ee5cdaa029f4a25b8b3d40718e6abTadashi G. Takaoka protected SettingsValues job(Resources res) { 45716c6f355700ee5cdaa029f4a25b8b3d40718e6abTadashi G. Takaoka return new SettingsValues(mPrefs, LatinIME.this); 45816c6f355700ee5cdaa029f4a25b8b3d40718e6abTadashi G. Takaoka } 45916c6f355700ee5cdaa029f4a25b8b3d40718e6abTadashi G. Takaoka }; 4606a7019ff5db19b1e3f8d7afbba71af813cab9a37Tadashi G. Takaoka mSettingsValues = job.runInLocale(mResources, mSubtypeSwitcher.getCurrentSubtypeLocale()); 46121af2f40c59de3ea5ec183aa278406bf28d5e3bdJean Chalard mFeedbackManager = new AudioAndHapticFeedbackManager(this, mSettingsValues); 46214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary()); 46317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard } 46417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 4650ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private void initSuggest() { 4666a7019ff5db19b1e3f8d7afbba71af813cab9a37Tadashi G. Takaoka final Locale subtypeLocale = mSubtypeSwitcher.getCurrentSubtypeLocale(); 4676a7019ff5db19b1e3f8d7afbba71af813cab9a37Tadashi G. Takaoka final String localeStr = subtypeLocale.toString(); 46836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 46918222f8c863e509538857b1fafca9c696fae2f55Tom Ouyang final Dictionary oldContactsDictionary; 47078ab80844b4f8e0369f4e86b2a02208197f9bd34Tadashi G. Takaoka if (mSuggest != null) { 47178ab80844b4f8e0369f4e86b2a02208197f9bd34Tadashi G. Takaoka oldContactsDictionary = mSuggest.getContactsDictionary(); 47278ab80844b4f8e0369f4e86b2a02208197f9bd34Tadashi G. Takaoka mSuggest.close(); 47378ab80844b4f8e0369f4e86b2a02208197f9bd34Tadashi G. Takaoka } else { 47478ab80844b4f8e0369f4e86b2a02208197f9bd34Tadashi G. Takaoka oldContactsDictionary = null; 47578ab80844b4f8e0369f4e86b2a02208197f9bd34Tadashi G. Takaoka } 4766a7019ff5db19b1e3f8d7afbba71af813cab9a37Tadashi G. Takaoka mSuggest = new Suggest(this, subtypeLocale); 47778ab80844b4f8e0369f4e86b2a02208197f9bd34Tadashi G. Takaoka if (mSettingsValues.mAutoCorrectEnabled) { 47878ab80844b4f8e0369f4e86b2a02208197f9bd34Tadashi G. Takaoka mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); 47978ab80844b4f8e0369f4e86b2a02208197f9bd34Tadashi G. Takaoka } 480e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 4816a7019ff5db19b1e3f8d7afbba71af813cab9a37Tadashi G. Takaoka mIsMainDictionaryAvailable = DictionaryFactory.isDictionaryAvailable(this, subtypeLocale); 4826a7019ff5db19b1e3f8d7afbba71af813cab9a37Tadashi G. Takaoka 483f6adff6227a15af105dbf39c57213a24bf16780bTom Ouyang if (USE_BINARY_USER_DICTIONARY) { 484f6adff6227a15af105dbf39c57213a24bf16780bTom Ouyang mUserDictionary = new UserBinaryDictionary(this, localeStr); 485f6adff6227a15af105dbf39c57213a24bf16780bTom Ouyang mIsUserDictionaryAvailable = ((UserBinaryDictionary)mUserDictionary).isEnabled(); 486f6adff6227a15af105dbf39c57213a24bf16780bTom Ouyang } else { 487f6adff6227a15af105dbf39c57213a24bf16780bTom Ouyang mUserDictionary = new UserDictionary(this, localeStr); 488f6adff6227a15af105dbf39c57213a24bf16780bTom Ouyang mIsUserDictionaryAvailable = ((UserDictionary)mUserDictionary).isEnabled(); 489f6adff6227a15af105dbf39c57213a24bf16780bTom Ouyang } 49078ab80844b4f8e0369f4e86b2a02208197f9bd34Tadashi G. Takaoka mSuggest.setUserDictionary(mUserDictionary); 491e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 49278ab80844b4f8e0369f4e86b2a02208197f9bd34Tadashi G. Takaoka resetContactsDictionary(oldContactsDictionary); 493e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa 49478ab80844b4f8e0369f4e86b2a02208197f9bd34Tadashi G. Takaoka mUserHistoryDictionary = new UserHistoryDictionary( 49578ab80844b4f8e0369f4e86b2a02208197f9bd34Tadashi G. Takaoka this, localeStr, Suggest.DIC_USER_HISTORY); 49678ab80844b4f8e0369f4e86b2a02208197f9bd34Tadashi G. Takaoka mSuggest.setUserHistoryDictionary(mUserHistoryDictionary); 497923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 49836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 49914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard /** 50014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * Resets the contacts dictionary in mSuggest according to the user settings. 50114051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * 50214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * This method takes an optional contacts dictionary to use. Since the contacts dictionary 50314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * does not depend on the locale, it can be reused across different instances of Suggest. 50414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * The dictionary will also be opened or closed as necessary depending on the settings. 50514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * 50614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard * @param oldContactsDictionary an optional dictionary to use, or null 50714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard */ 50818222f8c863e509538857b1fafca9c696fae2f55Tom Ouyang private void resetContactsDictionary(final Dictionary oldContactsDictionary) { 50914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard final boolean shouldSetDictionary = (null != mSuggest && mSettingsValues.mUseContactsDict); 51014051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard 51118222f8c863e509538857b1fafca9c696fae2f55Tom Ouyang final Dictionary dictionaryToUse; 51214051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (!shouldSetDictionary) { 51314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // Make sure the dictionary is closed. If it is already closed, this is a no-op, 51414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // so it's safe to call it anyways. 51514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (null != oldContactsDictionary) oldContactsDictionary.close(); 51614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard dictionaryToUse = null; 51714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } else if (null != oldContactsDictionary) { 51814051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // Make sure the old contacts dictionary is opened. If it is already open, this is a 51914051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard // no-op, so it's safe to call it anyways. 52018222f8c863e509538857b1fafca9c696fae2f55Tom Ouyang if (USE_BINARY_CONTACTS_DICTIONARY) { 52118222f8c863e509538857b1fafca9c696fae2f55Tom Ouyang ((ContactsBinaryDictionary)oldContactsDictionary).reopen(this); 52218222f8c863e509538857b1fafca9c696fae2f55Tom Ouyang } else { 52318222f8c863e509538857b1fafca9c696fae2f55Tom Ouyang ((ContactsDictionary)oldContactsDictionary).reopen(this); 52418222f8c863e509538857b1fafca9c696fae2f55Tom Ouyang } 52514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard dictionaryToUse = oldContactsDictionary; 52614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } else { 52718222f8c863e509538857b1fafca9c696fae2f55Tom Ouyang if (USE_BINARY_CONTACTS_DICTIONARY) { 52818222f8c863e509538857b1fafca9c696fae2f55Tom Ouyang dictionaryToUse = new ContactsBinaryDictionary(this, Suggest.DIC_CONTACTS, 5296a7019ff5db19b1e3f8d7afbba71af813cab9a37Tadashi G. Takaoka mSubtypeSwitcher.getCurrentSubtypeLocale()); 53018222f8c863e509538857b1fafca9c696fae2f55Tom Ouyang } else { 53118222f8c863e509538857b1fafca9c696fae2f55Tom Ouyang dictionaryToUse = new ContactsDictionary(this, Suggest.DIC_CONTACTS); 53218222f8c863e509538857b1fafca9c696fae2f55Tom Ouyang } 53314051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } 53414051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard 53514051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard if (null != mSuggest) { 53614051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard mSuggest.setContactsDictionary(dictionaryToUse); 53714051e2b5343db4b0531b7b4b806da0c09d6e251Jean Chalard } 538699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard } 539699094f9b6e0a4621e8b3cfab70b59c0c7c086bbJean Chalard 540cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard /* package private */ void resetSuggestMainDict() { 5416a7019ff5db19b1e3f8d7afbba71af813cab9a37Tadashi G. Takaoka final Locale subtypeLocale = mSubtypeSwitcher.getCurrentSubtypeLocale(); 5426a7019ff5db19b1e3f8d7afbba71af813cab9a37Tadashi G. Takaoka mSuggest.resetMainDict(this, subtypeLocale); 5436a7019ff5db19b1e3f8d7afbba71af813cab9a37Tadashi G. Takaoka mIsMainDictionaryAvailable = DictionaryFactory.isDictionaryAvailable(this, subtypeLocale); 544cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard } 545cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 546466741d8a78965b8509bf527344f289e50873092Mike LeBeau @Override 547466741d8a78965b8509bf527344f289e50873092Mike LeBeau public void onDestroy() { 548e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa if (mSuggest != null) { 549e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest.close(); 550e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa mSuggest = null; 551979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 552923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project unregisterReceiver(mReceiver); 553cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard unregisterReceiver(mDictionaryPackInstallReceiver); 554979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 555979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.onDestroy(); 556923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onDestroy(); 557923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 558923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 559923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 560923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onConfigurationChanged(Configuration conf) { 561dc64b138b5e3fb3706c0818d0a308fe6e36985b0Tadashi G. Takaoka mSubtypeSwitcher.onConfigurationChanged(conf); 562b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani // If orientation changed while predicting, commit the change 563f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka if (mDisplayOrientation != conf.orientation) { 564f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka mDisplayOrientation = conf.orientation; 565f94df382fb3f73c03cfef5f0a28856bf3f1c73daTadashi G. Takaoka mHandler.startOrientationChanging(); 5669351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 56766bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitTyped(ic, LastComposedWord.NOT_A_SEPARATOR); 568466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (ic != null) ic.finishComposingText(); // For voice input 5692fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka if (isShowingOptionDialog()) 5702fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka mOptionsDialog.dismiss(); 571b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 572923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onConfigurationChanged(conf); 573923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 574b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 575923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 576923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public View onCreateInputView() { 5776c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka return mKeyboardSwitcher.onCreateInputView(); 5786c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka } 5796c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka 5806c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka @Override 5816c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka public void setInputView(View view) { 5826c4add55f94ff729ef1aa35c4f8df3b086344f8aTadashi G. Takaoka super.setInputView(view); 583d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka mExtractArea = getWindow().getWindow().getDecorView() 584d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka .findViewById(android.R.id.extractArea); 585abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka mKeyPreviewBackingView = view.findViewById(R.id.key_preview_backing); 586913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsContainer = view.findViewById(R.id.suggestions_container); 587913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView = (SuggestionsView) view.findViewById(R.id.suggestions_view); 588913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) 589913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.setListener(this, view); 590f5fe245df0548ea0a8ec607f2392de0fe02c141dTadashi G. Takaoka if (LatinImeLogger.sVISUALDEBUG) { 591f5fe245df0548ea0a8ec607f2392de0fe02c141dTadashi G. Takaoka mKeyPreviewBackingView.setBackgroundColor(0x10FF0000); 592f5fe245df0548ea0a8ec607f2392de0fe02c141dTadashi G. Takaoka } 593923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 594923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 595923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 596c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka public void setCandidatesView(View view) { 597c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka // To ensure that CandidatesView will never be set. 598c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return; 599923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 600923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 601a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker @Override 602e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka public void onStartInput(EditorInfo editorInfo, boolean restarting) { 603e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mHandler.onStartInput(editorInfo, restarting); 60459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 60559f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 60659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka @Override 607e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka public void onStartInputView(EditorInfo editorInfo, boolean restarting) { 608e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka mHandler.onStartInputView(editorInfo, restarting); 60959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 61059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 61159f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka @Override 61259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInputView(boolean finishingInput) { 61359f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHandler.onFinishInputView(finishingInput); 61459f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 61538f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka 61659f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka @Override 61759f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka public void onFinishInput() { 61859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka mHandler.onFinishInput(); 61959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 62059f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 6219cc2c94c8b4bfd4e00e5d3478b9f6e520e791bc5Tadashi G. Takaoka @Override 6229cc2c94c8b4bfd4e00e5d3478b9f6e520e791bc5Tadashi G. Takaoka public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) { 6236a7019ff5db19b1e3f8d7afbba71af813cab9a37Tadashi G. Takaoka mSubtypeSwitcher.updateSubtype(subtype); 6249cc2c94c8b4bfd4e00e5d3478b9f6e520e791bc5Tadashi G. Takaoka } 6259cc2c94c8b4bfd4e00e5d3478b9f6e520e791bc5Tadashi G. Takaoka 626e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka private void onStartInputInternal(EditorInfo editorInfo, boolean restarting) { 627e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka super.onStartInput(editorInfo, restarting); 62859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka } 62959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka 6301cb08acaf3b4d58cbf4cb65f9fc3990b39e33f00Tadashi G. Takaoka @SuppressWarnings("deprecation") 631e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka private void onStartInputViewInternal(EditorInfo editorInfo, boolean restarting) { 632e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka super.onStartInputView(editorInfo, restarting); 63345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 634c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka LatinKeyboardView inputView = switcher.getKeyboardView(); 6358e09172df1bb176cc899940862c56bed9b9aec4esatok 636ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok if (editorInfo == null) { 637ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok Log.e(TAG, "Null EditorInfo in onStartInputView()"); 638ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok if (LatinImeLogger.sDBG) { 639ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok throw new NullPointerException("Null EditorInfo in onStartInputView()"); 640ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok } 641ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok return; 642ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok } 64389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (DEBUG) { 644ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok Log.d(TAG, "onStartInputView: editorInfo:" 645ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok + String.format("inputType=0x%08x imeOptions=0x%08x", 646ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok editorInfo.inputType, editorInfo.imeOptions)); 647b6fb5eb391987f3e426649a892cdcbf781957f5asatok Log.d(TAG, "All caps = " 648b6fb5eb391987f3e426649a892cdcbf781957f5asatok + ((editorInfo.inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0) 649b6fb5eb391987f3e426649a892cdcbf781957f5asatok + ", sentence caps = " 650b6fb5eb391987f3e426649a892cdcbf781957f5asatok + ((editorInfo.inputType & InputType.TYPE_TEXT_FLAG_CAP_SENTENCES) != 0) 651b6fb5eb391987f3e426649a892cdcbf781957f5asatok + ", word caps = " 652b6fb5eb391987f3e426649a892cdcbf781957f5asatok + ((editorInfo.inputType & InputType.TYPE_TEXT_FLAG_CAP_WORDS) != 0)); 653910b73127fa207dd26ec8124000262523b0aac0csatok } 6549bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 65548a7681e064ae259b840f0e757da2d716043d893Kurt Partridge ResearchLogger.latinIME_onStartInputViewInternal(editorInfo, mPrefs); 6569bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge } 6571cb08acaf3b4d58cbf4cb65f9fc3990b39e33f00Tadashi G. Takaoka if (InputAttributes.inPrivateImeOptions(null, NO_MICROPHONE_COMPAT, editorInfo)) { 6584f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka Log.w(TAG, "Deprecated private IME option specified: " 6594f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka + editorInfo.privateImeOptions); 6601cb08acaf3b4d58cbf4cb65f9fc3990b39e33f00Tadashi G. Takaoka Log.w(TAG, "Use " + getPackageName() + "." + NO_MICROPHONE + " instead"); 6614f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka } 6621cb08acaf3b4d58cbf4cb65f9fc3990b39e33f00Tadashi G. Takaoka if (InputAttributes.inPrivateImeOptions(getPackageName(), FORCE_ASCII, editorInfo)) { 6634f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka Log.w(TAG, "Deprecated private IME option specified: " 6644f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka + editorInfo.privateImeOptions); 6654f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka Log.w(TAG, "Use EditorInfo.IME_FLAG_FORCE_ASCII flag instead"); 6664f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka } 6674f5c3a2898315ff41cc735a195cfeb2937f22f70Tadashi G. Takaoka 6687ef235f53f2291f22ddf8c56be9860a218b25bbbTadashi G. Takaoka LatinImeLogger.onStartInputView(editorInfo); 669923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In landscape mode, this method gets called without the input view being created. 670979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (inputView == null) { 671923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 672923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 673923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 674b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette // Forward this event to the accessibility utilities, if enabled. 675b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette final AccessibilityUtils accessUtils = AccessibilityUtils.getInstance(); 676b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette if (accessUtils.isTouchExplorationEnabled()) { 677e7eac906c0a14b644d457beeb73a407fa1b63673Tadashi G. Takaoka accessUtils.onStartInputViewInternal(editorInfo, restarting); 678b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette } 679b0c8db018d53b103dcb4b699be27a4e1a2c2f92cAlan Viverette 6808d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka mSubtypeSwitcher.updateParametersOnStartInputView(); 6814ab730dbd34fad323063f2ffd31ce33de746668dsatok 682b2b1eb5ca5a52648eea70920b9bd745b07d3ddfaTadashi G. Takaoka // The EditorInfo might have a flag that affects fullscreen mode. 683b2b1eb5ca5a52648eea70920b9bd745b07d3ddfaTadashi G. Takaoka // Note: This call should be done by InputMethodService? 684b2b1eb5ca5a52648eea70920b9bd745b07d3ddfaTadashi G. Takaoka updateFullscreenMode(); 6851fead1d5f12928f90c723b5f7b88490cc7cd2a67Jean Chalard mLastSelectionStart = editorInfo.initialSelStart; 6861fead1d5f12928f90c723b5f7b88490cc7cd2a67Jean Chalard mLastSelectionEnd = editorInfo.initialSelEnd; 68780b66bb166f7f45adfcadcb84788477df9930828Jean Chalard mInputAttributes = new InputAttributes(editorInfo, isFullscreenMode()); 688ccc35f7fa74860a8d737a4e9ff01fc0168dd329dJean Chalard mApplicationSpecifiedCompletions = null; 689c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 690c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.closing(); 691c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mEnteredText = null; 6922692a8700737d8eed268039aa27b22a31669da08Jean Chalard resetComposingState(true /* alsoResetLastComposedWord */); 693c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mDeleteCount = 0; 694120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 695c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 69617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 69717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard updateCorrectionMode(); 6982ac5988f84b5c38d313951a3d7faddebf5f25e04Tadashi G. Takaoka updateSuggestionVisibility(mResources); 69917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 70017c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSuggest != null && mSettingsValues.mAutoCorrectEnabled) { 70117c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); 702549e295dc113bff50077c3c355dcd94af09a1b2fTadashi G. Takaoka } 70317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard 704cb389ef0d6e6eec737c249e1729c2a2cdc30f341Tadashi G. Takaoka switcher.loadKeyboard(editorInfo, mSettingsValues); 705c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 706913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) 707913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.clear(); 708913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShownInternal( 709913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka isSuggestionsStripVisible(), /* needsInputViewShown */ false); 710c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // Delay updating suggestions because keyboard input view may not be shown at this point. 711c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka mHandler.postUpdateSuggestions(); 712ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa mHandler.cancelDoubleSpacesTimer(); 713c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 714240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard inputView.setKeyPreviewPopupEnabled(mSettingsValues.mKeyPreviewPopupOn, 715240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard mSettingsValues.mKeyPreviewPopupDismissDelay); 716c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka inputView.setProximityCorrectionEnabled(true); 717c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 718c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); 719c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka } 720c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka 721923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 722e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka public void onWindowHidden() { 723e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka super.onWindowHidden(); 724f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 725e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka if (inputView != null) inputView.closing(); 726e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka } 727e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka 72859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void onFinishInputInternal() { 729923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onFinishInput(); 730a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 731979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 732979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 733f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 734d024ea605cc6b5b0b9fa1bd838d5b0ebd3901a5dKen Wakasa if (inputView != null) inputView.closing(); 7359ffb94fa1318f354692fab7abf4775fa14397a96Jean Chalard if (mUserHistoryDictionary != null) mUserHistoryDictionary.flushPendingWrites(); 736466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 737466741d8a78965b8509bf527344f289e50873092Mike LeBeau 73859f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka private void onFinishInputViewInternal(boolean finishingInput) { 7396495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa super.onFinishInputView(finishingInput); 740055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka mKeyboardSwitcher.onFinishInputView(); 741f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 7425f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka if (inputView != null) inputView.cancelAllMessages(); 743d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka // Remove pending messages related to update suggestions 744d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 7456495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa } 7466495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa 7476495bfc7a6f6bfa6ab82e7f062ee80f4b6b33368Ken Wakasa @Override 748923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onUpdateSelection(int oldSelStart, int oldSelEnd, 749923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int newSelStart, int newSelEnd, 750104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard int composingSpanStart, int composingSpanEnd) { 751923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, 752104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard composingSpanStart, composingSpanEnd); 753466741d8a78965b8509bf527344f289e50873092Mike LeBeau 754466741d8a78965b8509bf527344f289e50873092Mike LeBeau if (DEBUG) { 755466741d8a78965b8509bf527344f289e50873092Mike LeBeau Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart 756466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", ose=" + oldSelEnd 757025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lss=" + mLastSelectionStart 758025a5e356ec74dbed7f805a2e43adbb2a35320f8Ken Wakasa + ", lse=" + mLastSelectionEnd 759466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nss=" + newSelStart 760466741d8a78965b8509bf527344f289e50873092Mike LeBeau + ", nse=" + newSelEnd 761104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard + ", cs=" + composingSpanStart 762104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard + ", ce=" + composingSpanEnd); 763466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 7649bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 7659bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge ResearchLogger.latinIME_onUpdateSelection(mLastSelectionStart, mLastSelectionEnd, 7669bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, 7679bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge composingSpanEnd); 7689bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge } 769466741d8a78965b8509bf527344f289e50873092Mike LeBeau 770104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // TODO: refactor the following code to be less contrived. 771104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // "newSelStart != composingSpanEnd" || "newSelEnd != composingSpanEnd" means 772104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // that the cursor is not at the end of the composing span, or there is a selection. 773104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // "mLastSelectionStart != newSelStart" means that the cursor is not in the same place 774104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // as last time we were called (if there is a selection, it means the start hasn't 775104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // changed, so it's the end that did). 776104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard final boolean selectionChanged = (newSelStart != composingSpanEnd 777104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard || newSelEnd != composingSpanEnd) && mLastSelectionStart != newSelStart; 778104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // if composingSpanStart and composingSpanEnd are -1, it means there is no composing 779104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // span in the view - we can use that to narrow down whether the cursor was moved 780104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // by us or not. If we are composing a word but there is no composing span, then 781104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // we know for sure the cursor moved while we were composing and we should reset 782104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // the state. 783104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard final boolean noComposingSpan = composingSpanStart == -1 && composingSpanEnd == -1; 7844733609947c0ec74e460bd714fffca0518ade93aJean Chalard if (!mExpectingUpdateSelection) { 785cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard // TAKE CARE: there is a race condition when we enter this test even when the user 786cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard // did not explicitly move the cursor. This happens when typing fast, where two keys 787cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard // turn this flag on in succession and both onUpdateSelection() calls arrive after 788cd2286fff1ce0aaa5e3f60e55afba2299101207cJean Chalard // the second one - the first call successfully avoids this test, but the second one 789104453908064dcdbb4f10aa4150f1d79beafb408Jean Chalard // enters. For the moment we rely on noComposingSpan to further reduce the impact. 79051fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard 7919a2a11e65bd32d82754b3fcff74e9e3795327628Jean Chalard // TODO: the following is probably better done in resetEntireInputState(). 7929a2a11e65bd32d82754b3fcff74e9e3795327628Jean Chalard // it should only happen when the cursor moved, and the very purpose of the 7939a2a11e65bd32d82754b3fcff74e9e3795327628Jean Chalard // test below is to narrow down whether this happened or not. Likewise with 7949a2a11e65bd32d82754b3fcff74e9e3795327628Jean Chalard // the call to postUpdateShiftState. 79551fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard // We set this to NONE because after a cursor move, we don't want the space 79651fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard // state-related special processing to kick in. 79751fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard mSpaceState = SPACE_STATE_NONE; 79851fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard 7998a3d369840d6061692a19ceb1eb7267a50a9e056Jean Chalard if ((!mWordComposer.isComposingWord()) || selectionChanged || noComposingSpan) { 8002649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard resetEntireInputState(); 8014c0fe5719853325e51a8ff0652318e2afdaca97fJean Chalard } 802beb08b398fa73a26f2d42d6feec87e34a96ca2d9Tadashi G. Takaoka 803beb08b398fa73a26f2d42d6feec87e34a96ca2d9Tadashi G. Takaoka mHandler.postUpdateShiftState(); 8044733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 8054733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = false; 8066b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // TODO: Decide to call restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() or not 8076b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // here. It would probably be too expensive to call directly here but we may want to post a 8086b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // message to delay it. The point would be to unify behavior between backspace to the 8096b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // end of a word and manually put the pointer at the end of the word. 810466741d8a78965b8509bf527344f289e50873092Mike LeBeau 811979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Make a note of the cursor position 812979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionStart = newSelStart; 813979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mLastSelectionEnd = newSelEnd; 8147a8dac55278cedd838be325f56b4c52d973c61f5satok } 8157a8dac55278cedd838be325f56b4c52d973c61f5satok 816c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 817c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has clicked on the extracted text view, 818c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * when running in fullscreen mode. The default implementation hides 819913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * the suggestions view when this happens, but only if the extracted text 820c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * editor has a vertical scroll bar because its text doesn't fit. 821c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 822913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * cause the suggestions strip to disappear and re-appear. 823c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 824c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 825c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedTextClicked() { 826fe5364c825058f6c34c0f42135a5520b77525a28Jean Chalard if (isSuggestionsRequested()) return; 827c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 828c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedTextClicked(); 829c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 830c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 831c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani /** 832c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * This is called when the user has performed a cursor movement in the 833c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * extracted text view, when it is running in fullscreen mode. The default 834913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * implementation hides the suggestions view when a vertical movement 835c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * happens, but only if the extracted text editor has a vertical scroll bar 836c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * because its text doesn't fit. 837c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani * Here we override the behavior due to the possibility that a re-correction could 838913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * cause the suggestions strip to disappear and re-appear. 839c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani */ 840c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani @Override 841c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani public void onExtractedCursorMovement(int dx, int dy) { 842fe5364c825058f6c34c0f42135a5520b77525a28Jean Chalard if (isSuggestionsRequested()) return; 843c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 844c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani super.onExtractedCursorMovement(dx, dy); 845c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani } 846c1020c3aa65b1eef4c672564750c020d012c4ec2Amith Yamasani 847923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 848923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void hideWindow() { 849979f8690967ff5409fe18f5085858ccdb8e0ccf1satok LatinImeLogger.commit(); 850c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka mKeyboardSwitcher.onHideWindow(); 851979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 852923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (TRACE) Debug.stopMethodTracing(); 8536e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani if (mOptionsDialog != null && mOptionsDialog.isShowing()) { 8546e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog.dismiss(); 8556e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani mOptionsDialog = null; 8566e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani } 857923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.hideWindow(); 858923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 859923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 860923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 8611b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka public void onDisplayCompletions(CompletionInfo[] applicationSpecifiedCompletions) { 862979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (DEBUG) { 863a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa Log.i(TAG, "Received completions:"); 864bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok if (applicationSpecifiedCompletions != null) { 865bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok for (int i = 0; i < applicationSpecifiedCompletions.length; i++) { 866bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok Log.i(TAG, " #" + i + ": " + applicationSpecifiedCompletions[i]); 867bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok } 868923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 869923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 8709bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 8719bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge ResearchLogger.latinIME_onDisplayCompletions(applicationSpecifiedCompletions); 8729bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge } 873dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard if (mInputAttributes.mApplicationSpecifiedCompletionOn) { 8741b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mApplicationSpecifiedCompletions = applicationSpecifiedCompletions; 8751b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (applicationSpecifiedCompletions == null) { 876b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani clearSuggestions(); 877923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 878923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 879a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 880660776e09b9a3b321074a94721d901a035ca1b9fKen Wakasa final ArrayList<SuggestedWords.SuggestedWordInfo> applicationSuggestedWords = 88188bf1ba5263f5a5c1df367ddc401db4109ef8677Jean Chalard SuggestedWords.getFromApplicationSpecifiedCompletions( 8821dfef0336d5968dbd00b73489778cee1fb233d56Jean Chalard applicationSpecifiedCompletions); 883bdf6d1b18b3cebdde5f39d10066ead34be161bafJean Chalard final SuggestedWords suggestedWords = new SuggestedWords( 8847d55c891afdf7e74e505acac998a95a9ca7a9ec2Jean Chalard applicationSuggestedWords, 8852e2519ee914d4bf9462950553840557a4c19faedJean Chalard false /* typedWordValid */, 886bdf6d1b18b3cebdde5f39d10066ead34be161bafJean Chalard false /* hasAutoCorrectionCandidate */, 887b5eeb724fc98bb7169683539027d9ba54ffb8b14Jean Chalard false /* allowsToBeAutoCorrected */, 88803a35170751a635332c00bf6c272a0127a255cf6Jean Chalard false /* isPunctuationSuggestions */, 8890142b997bf18f5d07e83b3fd403f0b3ea4736040satok false /* isObsoleteSuggestions */, 8900142b997bf18f5d07e83b3fd403f0b3ea4736040satok false /* isPrediction */); 891979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // When in fullscreen mode, show completions generated by the application 8924e112d07821d34c1dedd21b086817be9fce2fd47Jean Chalard final boolean isAutoCorrection = false; 8937d55c891afdf7e74e505acac998a95a9ca7a9ec2Jean Chalard setSuggestions(suggestedWords, isAutoCorrection); 894dd931c47be1a4fe4cf86c8ad018e479c2cbdf8ceJean Chalard setAutoCorrectionIndicator(isAutoCorrection); 895b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard // TODO: is this the right thing to do? What should we auto-correct to in 896b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard // this case? This says to keep whatever the user typed. 897b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard mWordComposer.setAutoCorrection(mWordComposer.getTypedWord()); 898c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShown(true); 899923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 900923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 901923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 902c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka private void setSuggestionStripShownInternal(boolean shown, boolean needsInputViewShown) { 903913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka // TODO: Modify this if we support suggestions with hard keyboard 904913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (onEvaluateInputViewShown() && mSuggestionsContainer != null) { 905433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka final LatinKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); 906433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka final boolean inputViewShown = (keyboardView != null) ? keyboardView.isShown() : false; 907913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka final boolean shouldShowSuggestions = shown 908433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka && (needsInputViewShown ? inputViewShown : true); 9094b1780fa9571409d65d9797d47949ffafaf0f083Tadashi G. Takaoka if (isFullscreenMode()) { 910913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsContainer.setVisibility( 911913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka shouldShowSuggestions ? View.VISIBLE : View.GONE); 9127a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka } else { 913913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsContainer.setVisibility( 914913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka shouldShowSuggestions ? View.VISIBLE : View.INVISIBLE); 9157a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka } 916923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 917923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 918a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 919c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka private void setSuggestionStripShown(boolean shown) { 920c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka setSuggestionStripShownInternal(shown, /* needsInputViewShown */true); 921543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa } 922543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa 923c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka private void adjustInputViewHeight() { 924c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka if (mKeyPreviewBackingView.getHeight() > 0) { 925c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka return; 926c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka } 927c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka 928c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka final KeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); 929c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka if (keyboardView == null) return; 930c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka final int keyboardHeight = keyboardView.getHeight(); 931c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka final int suggestionsHeight = mSuggestionsContainer.getHeight(); 932c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka final int displayHeight = mResources.getDisplayMetrics().heightPixels; 933c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka final Rect rect = new Rect(); 934c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka mKeyPreviewBackingView.getWindowVisibleDisplayFrame(rect); 935c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka final int notificationBarHeight = rect.top; 936c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka final int remainingHeight = displayHeight - notificationBarHeight - suggestionsHeight 937c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka - keyboardHeight; 938c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka 939c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka final LayoutParams params = mKeyPreviewBackingView.getLayoutParams(); 940c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka params.height = mSuggestionsView.setMoreSuggestionsHeight(remainingHeight); 941c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka mKeyPreviewBackingView.setLayoutParams(params); 942c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka } 943c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka 944543dbdfdbda259aa56be9670480c7d802beba332Ken Wakasa @Override 945923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onComputeInsets(InputMethodService.Insets outInsets) { 946923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.onComputeInsets(outInsets); 947f60d09ac3086f308cafcee13ebcb94c562f9e58eTadashi G. Takaoka final KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 948913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (inputView == null || mSuggestionsContainer == null) 94946ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka return; 950c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka adjustInputViewHeight(); 951d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka // In fullscreen mode, the height of the extract area managed by InputMethodService should 952d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka // be considered. 953d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka // See {@link android.inputmethodservice.InputMethodService#onComputeInsets}. 954d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka final int extractHeight = isFullscreenMode() ? mExtractArea.getHeight() : 0; 955f4cf5b9952ae331806bf656a6f977a5ece47fe80satok final boolean backingGone = mKeyPreviewBackingView.getVisibility() == View.GONE; 956f4cf5b9952ae331806bf656a6f977a5ece47fe80satok int backingHeight = backingGone ? 0 : mKeyPreviewBackingView.getHeight(); 957f4cf5b9952ae331806bf656a6f977a5ece47fe80satok if (WORKAROUND_USE_LAST_BACKING_HEIGHT_WHEN_NOT_READY && !backingGone) { 958f4cf5b9952ae331806bf656a6f977a5ece47fe80satok if (backingHeight <= 0) { 959f4cf5b9952ae331806bf656a6f977a5ece47fe80satok backingHeight = sLastBackingHeight; 960f4cf5b9952ae331806bf656a6f977a5ece47fe80satok } else { 961f4cf5b9952ae331806bf656a6f977a5ece47fe80satok sLastBackingHeight = backingHeight; 962f4cf5b9952ae331806bf656a6f977a5ece47fe80satok } 963f4cf5b9952ae331806bf656a6f977a5ece47fe80satok } 96459010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka final int suggestionsHeight = (mSuggestionsContainer.getVisibility() == View.GONE) ? 0 96559010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka : mSuggestionsContainer.getHeight(); 966d44647e76f286256515ddac8cfc1ab29a2cbcf82Tadashi G. Takaoka final int extraHeight = extractHeight + backingHeight + suggestionsHeight; 967abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka int touchY = extraHeight; 9689e347d3d448e48229c46aad394ec9bd60cd5807bsatok // Need to set touchable region only if input view is being shown 969433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka final LatinKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); 970433ca6a46db30a321715da0f457974916668dff5Tadashi G. Takaoka if (keyboardView != null && keyboardView.isShown()) { 971913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsContainer.getVisibility() == View.VISIBLE) { 97259010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka touchY -= suggestionsHeight; 9739e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 9747a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka final int touchWidth = inputView.getWidth(); 975abb0c77af15a22b5d0953e477da8747cd5f2259dTadashi G. Takaoka final int touchHeight = inputView.getHeight() + extraHeight 9767a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka // Extend touchable region below the keyboard. 9777a3d3ae17f7a8ca0b44e9c92328a7de7cbc80f92Tadashi G. Takaoka + EXTENDED_TOUCHABLE_REGION_HEIGHT; 97813d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka outInsets.touchableInsets = InputMethodService.Insets.TOUCHABLE_INSETS_REGION; 97913d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka outInsets.touchableRegion.set(0, touchY, touchWidth, touchHeight); 9809e347d3d448e48229c46aad394ec9bd60cd5807bsatok } 98146ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka outInsets.contentTopInsets = touchY; 98246ca84584810dfe606e709b3fe283cbde8aba5f5Tadashi G. Takaoka outInsets.visibleTopInsets = touchY; 9839ec06c17d4b0c2d551d89152320d0cae4c061c77satok if (WORKAROUND_USE_LAST_BACKING_HEIGHT_WHEN_NOT_READY) { 984f4cf5b9952ae331806bf656a6f977a5ece47fe80satok if (LatinImeLogger.sDBG) { 985f4cf5b9952ae331806bf656a6f977a5ece47fe80satok Log.i(TAG, "--- insets: " + touchY + "," + backingHeight + "," + suggestionsHeight); 986f4cf5b9952ae331806bf656a6f977a5ece47fe80satok } 987f4cf5b9952ae331806bf656a6f977a5ece47fe80satok } 988923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 989a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 990923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 991979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public boolean onEvaluateFullscreenMode() { 9929751a626ec9b2e771afa5b3757e8f8498a328683Tadashi G. Takaoka // Reread resource value here, because this method is called by framework anytime as needed. 9939751a626ec9b2e771afa5b3757e8f8498a328683Tadashi G. Takaoka final boolean isFullscreenModeAllowed = 9949751a626ec9b2e771afa5b3757e8f8498a328683Tadashi G. Takaoka mSettingsValues.isFullscreenModeAllowed(getResources()); 9959751a626ec9b2e771afa5b3757e8f8498a328683Tadashi G. Takaoka return super.onEvaluateFullscreenMode() && isFullscreenModeAllowed; 99659010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka } 99759010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka 99859010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka @Override 99959010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka public void updateFullscreenMode() { 100059010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka super.updateFullscreenMode(); 1001f80b6a06992ae08ca3601f4fbc6da550fd9ac730Tadashi G. Takaoka 100259010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka if (mKeyPreviewBackingView == null) return; 1003549e295dc113bff50077c3c355dcd94af09a1b2fTadashi G. Takaoka // In fullscreen mode, no need to have extra space to show the key preview. 100459010a89b839ea181dc07588df21f3db29ee8bd1Tadashi G. Takaoka // If not, we should have extra space above the keyboard to show the key preview. 1005549e295dc113bff50077c3c355dcd94af09a1b2fTadashi G. Takaoka mKeyPreviewBackingView.setVisibility(isFullscreenMode() ? View.GONE : View.VISIBLE); 1006979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 1007979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 10082649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard // This will reset the whole input state to the starting state. It will clear 10092649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard // the composing word, reset the last composed word, tell the inputconnection 10102649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard // and the composingStateManager about it. 10112649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard private void resetEntireInputState() { 10122649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard resetComposingState(true /* alsoResetLastComposedWord */); 10132649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard updateSuggestions(); 10142649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard final InputConnection ic = getCurrentInputConnection(); 10152649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard if (ic != null) { 10162649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard ic.finishComposingText(); 10172649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard } 10182649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard } 10192649e42d756132ad763d6db5f9de1f901bbefd06Jean Chalard 10202692a8700737d8eed268039aa27b22a31669da08Jean Chalard private void resetComposingState(final boolean alsoResetLastComposedWord) { 10212692a8700737d8eed268039aa27b22a31669da08Jean Chalard mWordComposer.reset(); 10222692a8700737d8eed268039aa27b22a31669da08Jean Chalard if (alsoResetLastComposedWord) 10232692a8700737d8eed268039aa27b22a31669da08Jean Chalard mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; 10242692a8700737d8eed268039aa27b22a31669da08Jean Chalard } 10252692a8700737d8eed268039aa27b22a31669da08Jean Chalard 102666bb563535dbe3672f99f75bd71763a551444867Jean Chalard public void commitTyped(final InputConnection ic, final int separatorCode) { 1027196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (!mWordComposer.isComposingWord()) return; 10283651220327c051d8017045aa5e8919461507b3f8Jean Chalard final CharSequence typedWord = mWordComposer.getTypedWord(); 10293651220327c051d8017045aa5e8919461507b3f8Jean Chalard if (typedWord.length() > 0) { 1030cf9d92629cae88273805eaf7984fcfdd8afd11f5Jean Chalard mLastComposedWord = mWordComposer.commitWord( 103166bb563535dbe3672f99f75bd71763a551444867Jean Chalard LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, typedWord.toString(), 103266bb563535dbe3672f99f75bd71763a551444867Jean Chalard separatorCode); 10339351550dc6af7859e5280e16144c9386a37b976dKen Wakasa if (ic != null) { 10343651220327c051d8017045aa5e8919461507b3f8Jean Chalard ic.commitText(typedWord, 1); 1035d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 1036d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_commitText(typedWord); 1037d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 1038923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1039c24f66e18007b5aba32bfab8f86eb7f03fa6c1b7Jean Chalard addToUserHistoryDictionary(typedWord); 1040923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 10418558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa updateSuggestions(); 1042923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1043923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1044553e2f19c1607080ff874cb642237f947809cdb3Tadashi G. Takaoka public int getCurrentAutoCapsState() { 1045553e2f19c1607080ff874cb642237f947809cdb3Tadashi G. Takaoka if (!mSettingsValues.mAutoCap) return Constants.TextUtils.CAP_MODE_OFF; 104603ca17c8415854c4c949b92b66543c920562ac3dTadashi G. Takaoka 104703ca17c8415854c4c949b92b66543c920562ac3dTadashi G. Takaoka final EditorInfo ei = getCurrentInputEditorInfo(); 1048553e2f19c1607080ff874cb642237f947809cdb3Tadashi G. Takaoka if (ei == null) return Constants.TextUtils.CAP_MODE_OFF; 104903ca17c8415854c4c949b92b66543c920562ac3dTadashi G. Takaoka 105003ca17c8415854c4c949b92b66543c920562ac3dTadashi G. Takaoka final int inputType = ei.inputType; 1051553e2f19c1607080ff874cb642237f947809cdb3Tadashi G. Takaoka if ((inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0) { 1052553e2f19c1607080ff874cb642237f947809cdb3Tadashi G. Takaoka return TextUtils.CAP_MODE_CHARACTERS; 1053553e2f19c1607080ff874cb642237f947809cdb3Tadashi G. Takaoka } 105403ca17c8415854c4c949b92b66543c920562ac3dTadashi G. Takaoka 105503ca17c8415854c4c949b92b66543c920562ac3dTadashi G. Takaoka final boolean noNeedToCheckCapsMode = (inputType & (InputType.TYPE_TEXT_FLAG_CAP_SENTENCES 105603ca17c8415854c4c949b92b66543c920562ac3dTadashi G. Takaoka | InputType.TYPE_TEXT_FLAG_CAP_WORDS)) == 0; 1057553e2f19c1607080ff874cb642237f947809cdb3Tadashi G. Takaoka if (noNeedToCheckCapsMode) return Constants.TextUtils.CAP_MODE_OFF; 105803ca17c8415854c4c949b92b66543c920562ac3dTadashi G. Takaoka 10599351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1060553e2f19c1607080ff874cb642237f947809cdb3Tadashi G. Takaoka if (ic == null) return Constants.TextUtils.CAP_MODE_OFF; 106103ca17c8415854c4c949b92b66543c920562ac3dTadashi G. Takaoka // TODO: This blocking IPC call is heavy. Consider doing this without using IPC calls. 106203ca17c8415854c4c949b92b66543c920562ac3dTadashi G. Takaoka // Note: getCursorCapsMode() returns the current capitalization mode that is any 106303ca17c8415854c4c949b92b66543c920562ac3dTadashi G. Takaoka // combination of CAP_MODE_CHARACTERS, CAP_MODE_WORDS, and CAP_MODE_SENTENCES. 0 means none 106403ca17c8415854c4c949b92b66543c920562ac3dTadashi G. Takaoka // of them. 1065553e2f19c1607080ff874cb642237f947809cdb3Tadashi G. Takaoka return ic.getCursorCapsMode(inputType); 10661c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 10671c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 1068b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard // "ic" may be null 1069b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard private void swapSwapperAndSpaceWhileInBatchEdit(final InputConnection ic) { 1070b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard if (null == ic) return; 1071923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project CharSequence lastTwo = ic.getTextBeforeCursor(2, 0); 1072863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard // It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called. 1073923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastTwo != null && lastTwo.length() == 2 1074863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard && lastTwo.charAt(0) == Keyboard.CODE_SPACE) { 1075923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 1076d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 1077d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_deleteSurroundingText(2); 1078d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 1079923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(lastTwo.charAt(1) + " ", 1); 1080d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 1081d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_swapSwapperAndSpaceWhileInBatchEdit(); 1082d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 1083b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 10844ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 10854ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa } 10864ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1087120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private boolean maybeDoubleSpaceWhileInBatchEdit(final InputConnection ic) { 1088120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (mCorrectionMode == Suggest.CORRECTION_NONE) return false; 1089120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (ic == null) return false; 10902b4eabed2bfe982b91a994c145401d98894e6ef5Jean Chalard final CharSequence lastThree = ic.getTextBeforeCursor(3, 0); 1091923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (lastThree != null && lastThree.length() == 3 1092344af156744c6866090fb70f151efd66668c1e20Tadashi G. Takaoka && canBeFollowedByPeriod(lastThree.charAt(0)) 1093571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastThree.charAt(1) == Keyboard.CODE_SPACE 1094fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka && lastThree.charAt(2) == Keyboard.CODE_SPACE 1095fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka && mHandler.isAcceptingDoubleSpaces()) { 1096fc20f2198d6703d65eab22f40f9b8aa2c8e3a0eaTadashi G. Takaoka mHandler.cancelDoubleSpacesTimer(); 1097923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(2, 0); 1098923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(". ", 1); 1099d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 1100d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_doubleSpaceAutoPeriod(); 1101d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 1102b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1103120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return true; 1104923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1105120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return false; 1106923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1107a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1108344af156744c6866090fb70f151efd66668c1e20Tadashi G. Takaoka private static boolean canBeFollowedByPeriod(final int codePoint) { 1109344af156744c6866090fb70f151efd66668c1e20Tadashi G. Takaoka // TODO: Check again whether there really ain't a better way to check this. 1110344af156744c6866090fb70f151efd66668c1e20Tadashi G. Takaoka // TODO: This should probably be language-dependant... 1111344af156744c6866090fb70f151efd66668c1e20Tadashi G. Takaoka return Character.isLetterOrDigit(codePoint) 1112344af156744c6866090fb70f151efd66668c1e20Tadashi G. Takaoka || codePoint == Keyboard.CODE_SINGLE_QUOTE 1113344af156744c6866090fb70f151efd66668c1e20Tadashi G. Takaoka || codePoint == Keyboard.CODE_DOUBLE_QUOTE 1114344af156744c6866090fb70f151efd66668c1e20Tadashi G. Takaoka || codePoint == Keyboard.CODE_CLOSING_PARENTHESIS 1115344af156744c6866090fb70f151efd66668c1e20Tadashi G. Takaoka || codePoint == Keyboard.CODE_CLOSING_SQUARE_BRACKET 1116344af156744c6866090fb70f151efd66668c1e20Tadashi G. Takaoka || codePoint == Keyboard.CODE_CLOSING_CURLY_BRACKET 1117344af156744c6866090fb70f151efd66668c1e20Tadashi G. Takaoka || codePoint == Keyboard.CODE_CLOSING_ANGLE_BRACKET; 1118344af156744c6866090fb70f151efd66668c1e20Tadashi G. Takaoka } 1119344af156744c6866090fb70f151efd66668c1e20Tadashi G. Takaoka 1120b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard // "ic" may be null 11218fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka private static void removeTrailingSpaceWhileInBatchEdit(final InputConnection ic) { 11229a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic == null) return; 1123b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard final CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 11249a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (lastOne != null && lastOne.length() == 1 1125571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka && lastOne.charAt(0) == Keyboard.CODE_SPACE) { 11269a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa ic.deleteSurroundingText(1, 0); 1127d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 1128d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_deleteSurroundingText(1); 1129d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 11309a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 11319a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 11329a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa 1133c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka @Override 1134923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean addWordToDictionary(String word) { 1135f6adff6227a15af105dbf39c57213a24bf16780bTom Ouyang if (USE_BINARY_USER_DICTIONARY) { 1136f6adff6227a15af105dbf39c57213a24bf16780bTom Ouyang ((UserBinaryDictionary)mUserDictionary).addWordToUserDictionary(word, 128); 1137f6adff6227a15af105dbf39c57213a24bf16780bTom Ouyang } else { 1138f6adff6227a15af105dbf39c57213a24bf16780bTom Ouyang ((UserDictionary)mUserDictionary).addWordToUserDictionary(word, 128); 1139f6adff6227a15af105dbf39c57213a24bf16780bTom Ouyang } 11406558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // Suggestion strip should be updated after the operation of adding word to the 11416558253160e2039c87f424bd814f402ecd31de3bKen Wakasa // user dictionary 1142d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1143923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 1144923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1145923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 11468fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka private static boolean isAlphabet(int code) { 11478fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka return Character.isLetter(code); 1148923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1149a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1150e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka private void onSettingsKeyPressed() { 1151cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa if (isShowingOptionDialog()) return; 1152911b8f9d19c1c4903eeef29b43176cfeaa0e5d0cKen Wakasa showSubtypeSelectorAndSettings(); 11539a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 11549a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 1155cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa // Virtual codes representing custom requests. These are used in onCustomRequest() below. 1156cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa public static final int CODE_SHOW_INPUT_METHOD_PICKER = 1; 1157cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa 1158cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa @Override 1159cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa public boolean onCustomRequest(int requestCode) { 1160cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa if (isShowingOptionDialog()) return false; 1161cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa switch (requestCode) { 1162cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa case CODE_SHOW_INPUT_METHOD_PICKER: 116355d28fd1b2631a63542a647f693d8a8ed749bcf7Tadashi G. Takaoka if (ImfUtils.hasMultipleEnabledIMEsOrSubtypes( 116455d28fd1b2631a63542a647f693d8a8ed749bcf7Tadashi G. Takaoka this, true /* include aux subtypes */)) { 116579efbed76f638be298493107fa2d0cd1b5eb529esatok mImm.showInputMethodPicker(); 1166cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return true; 11679a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 1168cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return false; 11699a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 1170cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa return false; 11719a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 11729a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 11739a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok private boolean isShowingOptionDialog() { 11749a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok return mOptionsDialog != null && mOptionsDialog.isShowing(); 11759a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok } 11769a6a4d3d5f1ee52b56d349c002aa61c264d010d3satok 117705bfd189a88be79ddfc74d0ea21792e2fb78f2aaTadashi G. Takaoka private static int getActionId(Keyboard keyboard) { 117805bfd189a88be79ddfc74d0ea21792e2fb78f2aaTadashi G. Takaoka return keyboard != null ? keyboard.mId.imeActionId() : EditorInfo.IME_ACTION_NONE; 11797a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 11807a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka 11818f433a66b2e8b327d7854eb501cf0e93afed4117Tadashi G. Takaoka private void performEditorAction(int actionId) { 11827a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 11837a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka if (ic != null) { 11847a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka ic.performEditorAction(actionId); 1185d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 1186d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_performEditorAction(actionId); 1187d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 11887a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 11897a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 11907a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka 119181d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka private void handleLanguageSwitchKey() { 1192c1ca8815f59bb1bce25e521571a1d87c71bf3fc3Ken Wakasa final boolean includesOtherImes = mSettingsValues.mIncludesOtherImesInLanguageSwitchList; 119381d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka final IBinder token = getWindow().getWindow().getAttributes().token; 119481d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka if (mShouldSwitchToLastSubtype) { 11959cc2c94c8b4bfd4e00e5d3478b9f6e520e791bc5Tadashi G. Takaoka final InputMethodSubtype lastSubtype = mImm.getLastInputMethodSubtype(); 1196ae2388c7f799ab565f63d3ba83abaf3300475fd0Tadashi G. Takaoka final boolean lastSubtypeBelongsToThisIme = 1197ae2388c7f799ab565f63d3ba83abaf3300475fd0Tadashi G. Takaoka ImfUtils.checkIfSubtypeBelongsToThisImeAndEnabled(this, lastSubtype); 119881d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka if ((includesOtherImes || lastSubtypeBelongsToThisIme) 119981d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka && mImm.switchToLastInputMethod(token)) { 120081d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka mShouldSwitchToLastSubtype = false; 120181d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka } else { 120281d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka mImm.switchToNextInputMethod(token, !includesOtherImes); 120381d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka mShouldSwitchToLastSubtype = true; 120481d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka } 120581d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka } else { 120681d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka mImm.switchToNextInputMethod(token, !includesOtherImes); 120781d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka } 120881d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka } 120981d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka 12107a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka private void sendKeyCodePoint(int code) { 12117a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka // TODO: Remove this special handling of digit letters. 12127a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka // For backward compatibility. See {@link InputMethodService#sendKeyChar(char)}. 12137a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka if (code >= '0' && code <= '9') { 12147a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka super.sendKeyChar((char)code); 12157a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka return; 12167a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 12177a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka 12187a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 12197a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka if (ic != null) { 12207a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka final String text = new String(new int[] { code }, 0, 1); 12217a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka ic.commitText(text, text.length()); 1222d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 1223d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_sendKeyCodePoint(code); 1224d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 12257a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 12267a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka } 12277a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka 12285f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // Implementation of {@link KeyboardActionListener}. 12295a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 1230ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok public void onCodeInput(int primaryCode, int x, int y) { 1231175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka final long when = SystemClock.uptimeMillis(); 1232571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) { 1233923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mDeleteCount = 0; 1234923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1235923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mLastKeyTime = when; 1236fdd68f06579ab338f5d33115aa8300431c75b4faKurt Partridge 1237c166697e3f5ec600089987dbbff0be7f3e308565Ken Wakasa if (ProductionFlag.IS_EXPERIMENTAL) { 1238c166697e3f5ec600089987dbbff0be7f3e308565Ken Wakasa if (ResearchLogger.sIsLogging) { 1239c166697e3f5ec600089987dbbff0be7f3e308565Ken Wakasa ResearchLogger.getInstance().logKeyEvent(primaryCode, x, y); 1240c166697e3f5ec600089987dbbff0be7f3e308565Ken Wakasa } 1241fdd68f06579ab338f5d33115aa8300431c75b4faKurt Partridge } 1242fdd68f06579ab338f5d33115aa8300431c75b4faKurt Partridge 1243175acb8205fcc2a91de4059e8a12af49484af784Tadashi G. Takaoka final KeyboardSwitcher switcher = mKeyboardSwitcher; 1244120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // The space state depends only on the last character pressed and its own previous 1245120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // state. Here, we revert the space state to neutral if the key is actually modifying 1246120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // the input contents (any non-shift key), which is what we should do for 1247120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // all inputs that do not result in a special state. Each character handling is then 1248120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // free to override the state as they see fit. 1249120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final int spaceState = mSpaceState; 125070852c91dc7209d0aaa875a2cb0f79739c7398e6Jean Chalard if (!mWordComposer.isComposingWord()) mIsAutoCorrectionIndicatorOn = false; 1251ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa 1252ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa // TODO: Consolidate the double space timer, mLastKeyTime, and the space state. 1253ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa if (primaryCode != Keyboard.CODE_SPACE) { 1254ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa mHandler.cancelDoubleSpacesTimer(); 1255ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa } 1256ed631627cb2337b025f0e80df6fecf1e6e511dc4Ken Wakasa 1257c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard boolean didAutoCorrect = false; 1258923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project switch (primaryCode) { 1259571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_DELETE: 1260120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 1261120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard handleBackspace(spaceState); 12624189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka mDeleteCount++; 12634733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 126481d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka mShouldSwitchToLastSubtype = true; 1265140467b8b65eb9087a9b7f744dbb8a30481effe7Kurt Partridge LatinImeLogger.logOnDelete(x, y); 12664189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1267571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka case Keyboard.CODE_SHIFT: 1268e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: 12692a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka // Shift and symbol key is handled in onPressKey() and onReleaseKey(). 12704189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1271e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka case Keyboard.CODE_SETTINGS: 127293246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka onSettingsKeyPressed(); 12734189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 1274d2c5fdda862f6dd2a1e020cf674c35fbbc63fc92Tadashi G. Takaoka case Keyboard.CODE_SHORTCUT: 127593246652638f423d5220449f65495dea0639c750Tadashi G. Takaoka mSubtypeSwitcher.switchToShortcutIME(); 12764189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 12777a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka case Keyboard.CODE_ACTION_ENTER: 12788f433a66b2e8b327d7854eb501cf0e93afed4117Tadashi G. Takaoka performEditorAction(getActionId(switcher.getKeyboard())); 12797a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka break; 128005bfd189a88be79ddfc74d0ea21792e2fb78f2aaTadashi G. Takaoka case Keyboard.CODE_ACTION_NEXT: 12818f433a66b2e8b327d7854eb501cf0e93afed4117Tadashi G. Takaoka performEditorAction(EditorInfo.IME_ACTION_NEXT); 128205bfd189a88be79ddfc74d0ea21792e2fb78f2aaTadashi G. Takaoka break; 128305bfd189a88be79ddfc74d0ea21792e2fb78f2aaTadashi G. Takaoka case Keyboard.CODE_ACTION_PREVIOUS: 12848f433a66b2e8b327d7854eb501cf0e93afed4117Tadashi G. Takaoka performEditorAction(EditorInfo.IME_ACTION_PREVIOUS); 12854189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka break; 128681d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka case Keyboard.CODE_LANGUAGE_SWITCH: 128781d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka handleLanguageSwitchKey(); 128881d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka break; 12894189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka default: 12900b831ba2aaf7baf7be402f2245b225a04c28fadaTadashi G. Takaoka if (primaryCode == Keyboard.CODE_TAB 12910b831ba2aaf7baf7be402f2245b225a04c28fadaTadashi G. Takaoka && mInputAttributes.mEditorAction == EditorInfo.IME_ACTION_NEXT) { 12920b831ba2aaf7baf7be402f2245b225a04c28fadaTadashi G. Takaoka performEditorAction(EditorInfo.IME_ACTION_NEXT); 12930b831ba2aaf7baf7be402f2245b225a04c28fadaTadashi G. Takaoka break; 12940b831ba2aaf7baf7be402f2245b225a04c28fadaTadashi G. Takaoka } 1295120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 129617c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (mSettingsValues.isWordSeparator(primaryCode)) { 1297c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState); 12984189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } else { 12998dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); 13008dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka if (keyboard != null && keyboard.hasProximityCharsCorrection(primaryCode)) { 13018dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka handleCharacter(primaryCode, x, y, spaceState); 13028dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka } else { 13038dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka handleCharacter(primaryCode, NOT_A_TOUCH_COORDINATE, NOT_A_TOUCH_COORDINATE, 13048dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka spaceState); 13058dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka } 13064189eb23082fcd4bf8cfb2085d18e226e0e7ce13Tadashi G. Takaoka } 13074733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 130881d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka mShouldSwitchToLastSubtype = true; 13094733609947c0ec74e460bd714fffca0518ade93aJean Chalard break; 1310923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1311eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka switcher.onCodeInput(primaryCode); 1312125de3dfdf548359de890247907f2e6f430008ecJean Chalard // Reset after any single keystroke, except shift and symbol-shift 1313125de3dfdf548359de890247907f2e6f430008ecJean Chalard if (!didAutoCorrect && primaryCode != Keyboard.CODE_SHIFT 1314125de3dfdf548359de890247907f2e6f430008ecJean Chalard && primaryCode != Keyboard.CODE_SWITCH_ALPHA_SYMBOL) 1315c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard mLastComposedWord.deactivate(); 1316dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = null; 1317923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1318a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 13195a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 13208aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onTextInput(CharSequence text) { 13219351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1322923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return; 1323923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 132466bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitTyped(ic, LastComposedWord.NOT_A_SEPARATOR); 1325fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard text = specificTldProcessingOnTextInput(ic, text); 1326fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (SPACE_STATE_PHANTOM == mSpaceState) { 13277a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka sendKeyCodePoint(Keyboard.CODE_SPACE); 1328fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 1329923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.commitText(text, 1); 1330d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 1331d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_commitText(text); 1332d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 1333923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1334b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 13358cab0b56eb8db311f158b18a361d9ceb85cff482Tadashi G. Takaoka mKeyboardSwitcher.onCodeInput(Keyboard.CODE_OUTPUT_TEXT); 1336120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_NONE; 1337dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani mEnteredText = text; 13382692a8700737d8eed268039aa27b22a31669da08Jean Chalard resetComposingState(true /* alsoResetLastComposedWord */); 1339923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1340923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1341fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // ic may not be null 1342fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard private CharSequence specificTldProcessingOnTextInput(final InputConnection ic, 1343fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard final CharSequence text) { 1344fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (text.length() <= 1 || text.charAt(0) != Keyboard.CODE_PERIOD 1345fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard || !Character.isLetter(text.charAt(1))) { 1346fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // Not a tld: do nothing. 1347fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard return text; 1348fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 134912d67e6d5d5bd764117038f3f666d4d7da0c10eaJean Chalard // We have a TLD (or something that looks like this): make sure we don't add 135012d67e6d5d5bd764117038f3f666d4d7da0c10eaJean Chalard // a space even if currently in phantom mode. 135112d67e6d5d5bd764117038f3f666d4d7da0c10eaJean Chalard mSpaceState = SPACE_STATE_NONE; 1352fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard final CharSequence lastOne = ic.getTextBeforeCursor(1, 0); 1353fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (lastOne != null && lastOne.length() == 1 1354fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard && lastOne.charAt(0) == Keyboard.CODE_PERIOD) { 1355fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard return text.subSequence(1, text.length()); 1356fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } else { 1357fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard return text; 1358fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 1359fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 1360fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard 13615a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 13628aa3f5a3ad6095a3355841ce30bce4877319d0a0Tadashi G. Takaoka public void onCancelInput() { 136383e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka // User released a finger outside any key 13645f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka mKeyboardSwitcher.onCancelInput(); 136583e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka } 136683e63ace2a1bd5b3c27d26d914456c2b0def17c5Tadashi G. Takaoka 1367120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard private void handleBackspace(final int spaceState) { 1368504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1369504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka if (ic == null) return; 1370979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ic.beginBatchEdit(); 1371a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard handleBackspaceWhileInBatchEdit(spaceState, ic); 1372a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard ic.endBatchEdit(); 1373a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard } 1374979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1375a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard // "ic" may not be null. 1376a2a85d45e0618dc0dd7d224d5a0e7394d9003dc5Jean Chalard private void handleBackspaceWhileInBatchEdit(final int spaceState, final InputConnection ic) { 13772245c3b5b3691928b08fd6accf8d4a21fb35e26bJean Chalard // In many cases, we may have to put the keyboard in auto-shift state again. 1378beb08b398fa73a26f2d42d6feec87e34a96ca2d9Tadashi G. Takaoka mHandler.postUpdateShiftState(); 13792245c3b5b3691928b08fd6accf8d4a21fb35e26bJean Chalard 13805c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { 13815c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // Cancel multi-character input: remove the text we just entered. 13825c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // This is triggered on backspace after a key that inputs multiple characters, 13835c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // like the smiley key or the .com key. 1384d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge final int length = mEnteredText.length(); 1385d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ic.deleteSurroundingText(length, 0); 1386d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 1387d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_deleteSurroundingText(length); 1388d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 13895c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // If we have mEnteredText, then we know that mHasUncommittedTypedChars == false. 13905c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // In addition we know that spaceState is false, and that we should not be 13915c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard // reverting any autocorrect at this point. So we can safely return. 13925c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard return; 13935c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard } 13945c3ff4c9c86e073d994ad874abe9dae7a665d5c4Jean Chalard 1395196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (mWordComposer.isComposingWord()) { 13963651220327c051d8017045aa5e8919461507b3f8Jean Chalard final int length = mWordComposer.size(); 1397923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (length > 0) { 13989318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa mWordComposer.deleteLast(); 139977d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); 1400196d82cdd740580ed79d801483dbc282be85d076Jean Chalard // If we have deleted the last remaining character of a word, then we are not 1401196d82cdd740580ed79d801483dbc282be85d076Jean Chalard // isComposingWord() any more. 1402196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (!mWordComposer.isComposingWord()) { 1403196d82cdd740580ed79d801483dbc282be85d076Jean Chalard // Not composing word any more, so we can show bigrams. 1404cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.postUpdateBigramPredictions(); 140589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 1406196d82cdd740580ed79d801483dbc282be85d076Jean Chalard // Still composing a word, so we still have letters to deduce a suggestion from. 140789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.postUpdateSuggestions(); 140889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 1409923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1410923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.deleteSurroundingText(1, 0); 1411d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 1412d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_deleteSurroundingText(1); 1413d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 1414923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1415890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard } else { 14165935950d4431dd7eef18ebc370f2abeb614465d4Jean Chalard if (mLastComposedWord.canRevertCommit()) { 1417d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard Utils.Stats.onAutoCorrectionCancellation(); 14185935950d4431dd7eef18ebc370f2abeb614465d4Jean Chalard revertCommit(ic); 1419120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return; 1420120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1421d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard if (SPACE_STATE_DOUBLE == spaceState) { 14222124bc5bf5af31cf3d2789b70ebd2f24c815f5f4Jean Chalard if (revertDoubleSpaceWhileInBatchEdit(ic)) { 1423d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard // No need to reset mSpaceState, it has already be done (that's why we 1424d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard // receive it as a parameter) 1425d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard return; 1426d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard } 1427d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard } else if (SPACE_STATE_SWAP_PUNCTUATION == spaceState) { 1428d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard if (revertSwapPunctuation(ic)) { 1429d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard // Likewise 1430d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard return; 1431d2c69c7d1231c238afc9196dcb9cc2359de520cfJean Chalard } 14324733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 1433504e8d5171edae36ec464a5e0c72cee22bb9ac4dTadashi G. Takaoka 14344fef31510df542a3324426a6750950194d016086Jean Chalard // No cancelling of commit/double space/swap: we have a regular backspace. 14354fef31510df542a3324426a6750950194d016086Jean Chalard // We should backspace one char and restart suggestion if at the end of a word. 14364fef31510df542a3324426a6750950194d016086Jean Chalard if (mLastSelectionStart != mLastSelectionEnd) { 14374fef31510df542a3324426a6750950194d016086Jean Chalard // If there is a selection, remove it. 14384fef31510df542a3324426a6750950194d016086Jean Chalard final int lengthToDelete = mLastSelectionEnd - mLastSelectionStart; 14394fef31510df542a3324426a6750950194d016086Jean Chalard ic.setSelection(mLastSelectionEnd, mLastSelectionEnd); 14404fef31510df542a3324426a6750950194d016086Jean Chalard ic.deleteSurroundingText(lengthToDelete, 0); 1441d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 1442d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_deleteSurroundingText(lengthToDelete); 1443d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 14446558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } else { 14454fef31510df542a3324426a6750950194d016086Jean Chalard // There is no selection, just delete one character. 14464fef31510df542a3324426a6750950194d016086Jean Chalard if (NOT_A_CURSOR_POSITION == mLastSelectionEnd) { 14474fef31510df542a3324426a6750950194d016086Jean Chalard // This should never happen. 14484fef31510df542a3324426a6750950194d016086Jean Chalard Log.e(TAG, "Backspace when we don't know the selection position"); 14496558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 14504fef31510df542a3324426a6750950194d016086Jean Chalard ic.deleteSurroundingText(1, 0); 1451d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 1452d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_deleteSurroundingText(1); 1453d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 14544fef31510df542a3324426a6750950194d016086Jean Chalard if (mDeleteCount > DELETE_ACCELERATE_AT) { 14554fef31510df542a3324426a6750950194d016086Jean Chalard ic.deleteSurroundingText(1, 0); 1456d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 1457d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_deleteSurroundingText(1); 1458d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 1459edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard } 1460923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 14614fef31510df542a3324426a6750950194d016086Jean Chalard if (isSuggestionsRequested()) { 14624fef31510df542a3324426a6750950194d016086Jean Chalard restartSuggestionsOnWordBeforeCursorIfAtEndOfWord(ic); 14634fef31510df542a3324426a6750950194d016086Jean Chalard } 1464923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1465923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1466923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1467e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard // ic may be null 1468e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard private boolean maybeStripSpaceWhileInBatchEdit(final InputConnection ic, final int code, 1469e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard final int spaceState, final boolean isFromSuggestionStrip) { 1470e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard if (Keyboard.CODE_ENTER == code && SPACE_STATE_SWAP_PUNCTUATION == spaceState) { 1471e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard removeTrailingSpaceWhileInBatchEdit(ic); 1472e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard return false; 1473e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } else if ((SPACE_STATE_WEAK == spaceState 1474e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard || SPACE_STATE_SWAP_PUNCTUATION == spaceState) 1475e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard && isFromSuggestionStrip) { 1476b141c9cd3f6785bc0a4e1f5385f4e6e2e17955bbJean Chalard if (mSettingsValues.isWeakSpaceSwapper(code)) { 1477e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard return true; 1478e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } else { 1479b141c9cd3f6785bc0a4e1f5385f4e6e2e17955bbJean Chalard if (mSettingsValues.isWeakSpaceStripper(code)) { 1480e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard removeTrailingSpaceWhileInBatchEdit(ic); 1481e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 1482e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard return false; 1483e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 1484e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } else { 1485e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard return false; 1486e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 1487e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 1488e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard 1489ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok private void handleCharacter(final int primaryCode, final int x, 1490120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final int y, final int spaceState) { 1491b715299125e8fbaaa941d994217baf823e6c4013Jean Chalard final InputConnection ic = getCurrentInputConnection(); 1492dafa7a8e15447544842975047f831883e67700c5Jean Chalard if (null != ic) ic.beginBatchEdit(); 1493dafa7a8e15447544842975047f831883e67700c5Jean Chalard // TODO: if ic is null, does it make any sense to call this? 1494ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok handleCharacterWhileInBatchEdit(primaryCode, x, y, spaceState, ic); 1495dafa7a8e15447544842975047f831883e67700c5Jean Chalard if (null != ic) ic.endBatchEdit(); 1496dafa7a8e15447544842975047f831883e67700c5Jean Chalard } 1497dafa7a8e15447544842975047f831883e67700c5Jean Chalard 1498dafa7a8e15447544842975047f831883e67700c5Jean Chalard // "ic" may be null without this crashing, but the behavior will be really strange 1499ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok private void handleCharacterWhileInBatchEdit(final int primaryCode, 1500dafa7a8e15447544842975047f831883e67700c5Jean Chalard final int x, final int y, final int spaceState, final InputConnection ic) { 1501196d82cdd740580ed79d801483dbc282be85d076Jean Chalard boolean isComposingWord = mWordComposer.isComposingWord(); 1502fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard 1503fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (SPACE_STATE_PHANTOM == spaceState && 1504fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard !mSettingsValues.isSymbolExcludedFromWordSeparators(primaryCode)) { 1505fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (isComposingWord) { 1506fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // Sanity check 1507fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard throw new RuntimeException("Should not be composing here"); 1508fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 15097a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka sendKeyCodePoint(Keyboard.CODE_SPACE); 1510fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } 1511fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard 1512d5cd7e64aa30096241f63e47a9169699bdd98231Jean Chalard // NOTE: isCursorTouchingWord() is a blocking IPC call, so it often takes several 1513d5cd7e64aa30096241f63e47a9169699bdd98231Jean Chalard // dozen milliseconds. Avoid calling it as much as possible, since we are on the UI 1514d5cd7e64aa30096241f63e47a9169699bdd98231Jean Chalard // thread here. 1515d5cd7e64aa30096241f63e47a9169699bdd98231Jean Chalard if (!isComposingWord && (isAlphabet(primaryCode) 1516e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard || mSettingsValues.isSymbolExcludedFromWordSeparators(primaryCode)) 1517d5cd7e64aa30096241f63e47a9169699bdd98231Jean Chalard && isSuggestionsRequested() && !isCursorTouchingWord()) { 1518736b109e1692374f5a2739885c8f931dbb8be1f2Jean Chalard // Reset entirely the composing state anyway, then start composing a new word unless 1519736b109e1692374f5a2739885c8f931dbb8be1f2Jean Chalard // the character is a single quote. The idea here is, single quote is not a 1520736b109e1692374f5a2739885c8f931dbb8be1f2Jean Chalard // separator and it should be treated as a normal character, except in the first 1521736b109e1692374f5a2739885c8f931dbb8be1f2Jean Chalard // position where it should not start composing a word. 1522736b109e1692374f5a2739885c8f931dbb8be1f2Jean Chalard isComposingWord = (Keyboard.CODE_SINGLE_QUOTE != primaryCode); 1523736b109e1692374f5a2739885c8f931dbb8be1f2Jean Chalard // Here we don't need to reset the last composed word. It will be reset 1524736b109e1692374f5a2739885c8f931dbb8be1f2Jean Chalard // when we commit this one, if we ever do; if on the other hand we backspace 1525736b109e1692374f5a2739885c8f931dbb8be1f2Jean Chalard // it entirely and resume suggestions on the previous word, we'd like to still 1526736b109e1692374f5a2739885c8f931dbb8be1f2Jean Chalard // have touch coordinates for it. 1527736b109e1692374f5a2739885c8f931dbb8be1f2Jean Chalard resetComposingState(false /* alsoResetLastComposedWord */); 1528736b109e1692374f5a2739885c8f931dbb8be1f2Jean Chalard clearSuggestions(); 1529923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 15307b5bc1ff4d4694045e69e6aff8a2b5365ff882d1Jean Chalard if (isComposingWord) { 1531ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok mWordComposer.add( 1532ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok primaryCode, x, y, mKeyboardSwitcher.getKeyboardView().getKeyDetector()); 1533923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 15341c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani // If it's the first letter, make note of auto-caps state 15359318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa if (mWordComposer.size() == 1) { 1536553e2f19c1607080ff874cb642237f947809cdb3Tadashi G. Takaoka mWordComposer.setAutoCapitalized( 1537553e2f19c1607080ff874cb642237f947809cdb3Tadashi G. Takaoka getCurrentAutoCapsState() != Constants.TextUtils.CAP_MODE_OFF); 15381c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 153977d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); 1540923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1541d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1542923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1543e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard final boolean swapWeakSpace = maybeStripSpaceWhileInBatchEdit(ic, primaryCode, 1544e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard spaceState, KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x); 1545863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard 15467a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka sendKeyCodePoint(primaryCode); 1547e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard 1548e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard if (swapWeakSpace) { 1549e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard swapSwapperAndSpaceWhileInBatchEdit(ic); 1550e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard mSpaceState = SPACE_STATE_WEAK; 1551e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 15525262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // Some characters are not word separators, yet they don't start a new 15535262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // composing span. For these, we haven't changed the suggestion strip, and 15545262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // if the "add to dictionary" hint is shown, we should do so now. Examples of 15555262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // such characters include single quote, dollar, and others; the exact list is 15565262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // the list of characters for which we enter handleCharacterWhileInBatchEdit 15575262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard // that don't match the test if ((isAlphabet...)) at the top of this method. 15585262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard if (null != mSuggestionsView && mSuggestionsView.dismissAddToDictionaryHint()) { 15595262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard mHandler.postUpdateBigramPredictions(); 15605262fe8832e69b5d4b2c575524da3757435644f0Jean Chalard } 1561e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard } 1562e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard Utils.Stats.onNonSeparator((char)primaryCode, x, y); 1563923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1564923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1565c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard // Returns true if we did an autocorrection, false otherwise. 1566c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard private boolean handleSeparator(final int primaryCode, final int x, final int y, 1567120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final int spaceState) { 156855b10796522b871c1e04d6f2254fdff5dc7aced4Ken Wakasa // Should dismiss the "Touch again to save" message when handling separator 1569913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) { 1570cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.cancelUpdateBigramPredictions(); 1571d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 15726558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 15736558253160e2039c87f424bd814f402ecd31de3bKen Wakasa 1574c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard boolean didAutoCorrect = false; 1575923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Handle separator 15761b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka final InputConnection ic = getCurrentInputConnection(); 1577923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1578923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.beginBatchEdit(); 1579923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1580196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (mWordComposer.isComposingWord()) { 1581923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // In certain languages where single quote is a separator, it's better 1582a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker // not to auto correct, but accept the typed word. For instance, 1583923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // in Italian dov' should not be expanded to dove' because the elision 1584923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // requires the last vowel to be removed. 1585f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled 1586dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard && !mInputAttributes.mInputTypeNoAutoCorrect; 158717c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (shouldAutoCorrect && primaryCode != Keyboard.CODE_SINGLE_QUOTE) { 1588f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard commitCurrentAutoCorrection(primaryCode, ic); 1589c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard didAutoCorrect = true; 1590923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 159166bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitTyped(ic, primaryCode); 1592923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1593923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 15944ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa 1595e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard final boolean swapWeakSpace = maybeStripSpaceWhileInBatchEdit(ic, primaryCode, spaceState, 1596e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x); 1597863f95b6052e5d9d4fb1ac5dc283c464db9f29c3Jean Chalard 159800ed3be95cee472685bcba1ea861ac75c61db690Jean Chalard if (SPACE_STATE_PHANTOM == spaceState && 159900ed3be95cee472685bcba1ea861ac75c61db690Jean Chalard mSettingsValues.isPhantomSpacePromotingSymbol(primaryCode)) { 160000ed3be95cee472685bcba1ea861ac75c61db690Jean Chalard sendKeyCodePoint(Keyboard.CODE_SPACE); 160100ed3be95cee472685bcba1ea861ac75c61db690Jean Chalard } 16027a39bd4454664b5c37b30e9b5362ddbcdce3b374Tadashi G. Takaoka sendKeyCodePoint(primaryCode); 160389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 160489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (Keyboard.CODE_SPACE == primaryCode) { 1605120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (isSuggestionsRequested()) { 1606120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard if (maybeDoubleSpaceWhileInBatchEdit(ic)) { 1607120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_DOUBLE; 1608120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } else if (!isShowingPunctuationList()) { 1609120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mSpaceState = SPACE_STATE_WEAK; 1610120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1611126698fdd256a2e3734634d3b923cabd800064baJean Chalard } 1612120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 1613120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard mHandler.startDoubleSpacesTimer(); 161489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (!isCursorTouchingWord()) { 161589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard mHandler.cancelUpdateSuggestions(); 1616cb3320179d39a7983874697a0aa428b127675c9dJean Chalard mHandler.postUpdateBigramPredictions(); 161789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 161889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 1619fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard if (swapWeakSpace) { 1620120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard swapSwapperAndSpaceWhileInBatchEdit(ic); 16214721427c7de3600f6fe7dfff16508a6a974fb3e4Jean Chalard mSpaceState = SPACE_STATE_SWAP_PUNCTUATION; 1622fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard } else if (SPACE_STATE_PHANTOM == spaceState) { 1623fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // If we are in phantom space state, and the user presses a separator, we want to 1624fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // stay in phantom space state so that the next keypress has a chance to add the 1625fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // space. For example, if I type "Good dat", pick "day" from the suggestion strip 1626fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // then insert a comma and go on to typing the next word, I want the space to be 1627fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // inserted automatically before the next word, the same way it is when I don't 1628fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // input the comma. 1629fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard mSpaceState = SPACE_STATE_PHANTOM; 1630120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 1631120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 163289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Set punctuation right away. onUpdateSelection will fire but tests whether it is 163389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // already displayed or not, so it's okay. 163455b9d333c5d260cb5da3f6a2d872bda8c03478d7Tadashi G. Takaoka setPunctuationSuggestions(); 1635923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1636120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 1637406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard Utils.Stats.onSeparator((char)primaryCode, x, y); 1638120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 1639923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 1640923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project ic.endBatchEdit(); 1641923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1642c7c152de4b42853086fc6fd918387ad0583d0e3eJean Chalard return didAutoCorrect; 1643923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1644466741d8a78965b8509bf527344f289e50873092Mike LeBeau 164577d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard private CharSequence getTextWithUnderline(final CharSequence text) { 16460a59ac2ba88ac1f99151d9336136bc6fe7d416c0Jean Chalard return mIsAutoCorrectionIndicatorOn 164777d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(this, text) 1648fda847a870829f1491cbd5325f9c985213081149Jean Chalard : text; 164977d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard } 165077d59b0691b8a9bd6cb336f07c175b88db53bbc0Jean Chalard 1651923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private void handleClose() { 165266bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitTyped(getCurrentInputConnection(), LastComposedWord.NOT_A_SEPARATOR); 1653923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project requestHideSelf(0); 1654c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); 16551679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka if (inputView != null) 16561679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka inputView.closing(); 1657923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1658923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 16597a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isSuggestionsRequested() { 1660dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard return mInputAttributes.mIsSettingsSuggestionStripOn 1661c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka && (mCorrectionMode > 0 || isShowingSuggestionsStrip()); 1662923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1663a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 16647a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isShowingPunctuationList() { 1665cb8cb95d0afd340de9f1a0e15948f0068d2450bcKen Wakasa if (mSuggestionsView == null) return false; 1666913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka return mSettingsValues.mSuggestPuncList == mSuggestionsView.getSuggestions(); 16677599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 16687599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 16697a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isShowingSuggestionsStrip() { 16707599cfea4a2d56f4779452ec8e8742f7b9629cc0satok return (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_VALUE) 16717599cfea4a2d56f4779452ec8e8742f7b9629cc0satok || (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE 167238f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka && mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT); 16737599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 16747599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 1675913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka public boolean isSuggestionsStripVisible() { 1676913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView == null) 1677b5e00d5841b946de8970875231456228ae0eb6b1Ken Wakasa return false; 1678d0c5f9395a1b94e8425982e353d090f972dc44f0Jean Chalard if (mSuggestionsView.isShowingAddToDictionaryHint()) 16799fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 16809fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka if (!isShowingSuggestionsStrip()) 16819fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return false; 1682dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard if (mInputAttributes.mApplicationSpecifiedCompletionOn) 16839fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return true; 16849fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka return isSuggestionsRequested(); 1685923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1686923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1687409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void switchToKeyboardView() { 1688060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (DEBUG) { 1689060efb6d82af1f896d90cb845c8ae07c726f85e1satok Log.d(TAG, "Switch to keyboard view."); 1690060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 16919bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 16929bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge ResearchLogger.latinIME_switchToKeyboardView(); 16939bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge } 1694c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka View v = mKeyboardSwitcher.getKeyboardView(); 1695060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (v != null) { 1696060efb6d82af1f896d90cb845c8ae07c726f85e1satok // Confirms that the keyboard view doesn't have parent view. 1697060efb6d82af1f896d90cb845c8ae07c726f85e1satok ViewParent p = v.getParent(); 1698060efb6d82af1f896d90cb845c8ae07c726f85e1satok if (p != null && p instanceof ViewGroup) { 1699060efb6d82af1f896d90cb845c8ae07c726f85e1satok ((ViewGroup) p).removeView(v); 17005a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } 1701060efb6d82af1f896d90cb845c8ae07c726f85e1satok setInputView(v); 1702060efb6d82af1f896d90cb845c8ae07c726f85e1satok } 1703913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShown(isSuggestionsStripVisible()); 1704060efb6d82af1f896d90cb845c8ae07c726f85e1satok updateInputViewShown(); 1705060efb6d82af1f896d90cb845c8ae07c726f85e1satok mHandler.postUpdateSuggestions(); 1706466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1707466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1708409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void clearSuggestions() { 1709dd931c47be1a4fe4cf86c8ad018e479c2cbdf8ceJean Chalard setSuggestions(SuggestedWords.EMPTY, false); 17107204eab3da916d8873b7eeee4b4528a6b82de19cJean Chalard setAutoCorrectionIndicator(false); 1711466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1712466741d8a78965b8509bf527344f289e50873092Mike LeBeau 17132be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard private void setSuggestions(final SuggestedWords words, final boolean isAutoCorrection) { 1714913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) { 1715913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.setSuggestions(words); 1716dd931c47be1a4fe4cf86c8ad018e479c2cbdf8ceJean Chalard mKeyboardSwitcher.onAutoCorrectionStateChanged(isAutoCorrection); 1717466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1718d02783cb63293507e8544ea60d07559092ce83d4Jean Chalard } 1719ec780e2868962bf17f0dfd35d36895f543bde40asatok 172038e535e59676ac4d7bf27026fe3e16fcd9eb292eJean Chalard private void setAutoCorrectionIndicator(final boolean newAutoCorrectionIndicator) { 1721ec780e2868962bf17f0dfd35d36895f543bde40asatok // Put a blue underline to a word in TextView which will be auto-corrected. 1722ec780e2868962bf17f0dfd35d36895f543bde40asatok final InputConnection ic = getCurrentInputConnection(); 17232be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard if (ic == null) return; 17242be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard if (mIsAutoCorrectionIndicatorOn != newAutoCorrectionIndicator 17252be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard && mWordComposer.isComposingWord()) { 17262be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard mIsAutoCorrectionIndicatorOn = newAutoCorrectionIndicator; 17272be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard final CharSequence textWithUnderline = 17282be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard getTextWithUnderline(mWordComposer.getTypedWord()); 17292be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard ic.setComposingText(textWithUnderline, 1); 1730ec780e2868962bf17f0dfd35d36895f543bde40asatok } 1731466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 1732466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1733409220583333bdf06290dd9fd42f91b5c0d1b11asatok public void updateSuggestions() { 1734923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project // Check if we have a suggestion engine attached. 1735911b8f9d19c1c4903eeef29b43176cfeaa0e5d0cKen Wakasa if ((mSuggest == null || !isSuggestionsRequested())) { 1736edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard if (mWordComposer.isComposingWord()) { 1737edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard Log.w(TAG, "Called updateSuggestions but suggestions were not requested!"); 1738edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard mWordComposer.setAutoCorrection(mWordComposer.getTypedWord()); 1739edc6395d9bdbb46082c8582ee92f6ba184914d59Jean Chalard } 1740923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1741923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1742466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1743cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard mHandler.cancelUpdateSuggestions(); 1744cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard mHandler.cancelUpdateBigramPredictions(); 1745cd95a365586b2b5f9a3639b72a2befdac7ada8a4Jean Chalard 1746196d82cdd740580ed79d801483dbc282be85d076Jean Chalard if (!mWordComposer.isComposingWord()) { 1747ca26f20fa4903de46e374babbfba8c8a1a5cac93satok setPunctuationSuggestions(); 1748923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1749923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1750979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 17519f67e12a0e3f77985fb8bafe0db4c00e32317b9asatok // TODO: May need a better way of retrieving previous word 175240f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final InputConnection ic = getCurrentInputConnection(); 175340f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final CharSequence prevWord; 175440f7efc172928bdd6048e91421a766abe5b22996Jean Chalard if (null == ic) { 175540f7efc172928bdd6048e91421a766abe5b22996Jean Chalard prevWord = null; 175640f7efc172928bdd6048e91421a766abe5b22996Jean Chalard } else { 175740f7efc172928bdd6048e91421a766abe5b22996Jean Chalard prevWord = EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators); 175840f7efc172928bdd6048e91421a766abe5b22996Jean Chalard } 1759dc5dfe37e06eb1d550d7aa5156cff226334d4e1eJean Chalard 1760dc5dfe37e06eb1d550d7aa5156cff226334d4e1eJean Chalard final CharSequence typedWord = mWordComposer.getTypedWord(); 17612be7a37acfd498bfc83347597bfb8cb216a310ebJean Chalard // getSuggestedWords handles gracefully a null value of prevWord 17625b0643f50d8c363296360f3ceaf32f7edc157141Jean Chalard final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer, 17633708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(), mCorrectionMode); 1764923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1765a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // Basically, we update the suggestion strip only when suggestion count > 1. However, 1766a776b7fc4a0d2c7f05eaed107e9d5db3b575b9d0Ken Wakasa // there is an exception: We update the suggestion strip whenever typed word's length 1767f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // is 1 or typed word is found in dictionary, regardless of suggestion count. Actually, 1768f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // in most cases, suggestion count is 1 when typed word's length is 1, but we do always 1769f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // need to clear the previous state when the user starts typing a word (i.e. typed word's 1770f3df63a93a8f623e2aca5895ee749bd297b58d12Tadashi G. Takaoka // length == 1). 17715b0643f50d8c363296360f3ceaf32f7edc157141Jean Chalard if (suggestedWords.size() > 1 || typedWord.length() == 1 17725b0643f50d8c363296360f3ceaf32f7edc157141Jean Chalard || !suggestedWords.mAllowsToBeAutoCorrected 1773838629aea00ce90231df97f1dae3d8273ba80cbdJean Chalard || mSuggestionsView.isShowingAddToDictionaryHint()) { 17745b0643f50d8c363296360f3ceaf32f7edc157141Jean Chalard showSuggestions(suggestedWords, typedWord); 1775838629aea00ce90231df97f1dae3d8273ba80cbdJean Chalard } else { 1776838629aea00ce90231df97f1dae3d8273ba80cbdJean Chalard SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions(); 1777838629aea00ce90231df97f1dae3d8273ba80cbdJean Chalard if (previousSuggestions == mSettingsValues.mSuggestPuncList) { 1778838629aea00ce90231df97f1dae3d8273ba80cbdJean Chalard previousSuggestions = SuggestedWords.EMPTY; 1779fe1a6d961cf039357f061482461e4d2e951ad346satok } 17804ee186920e642ae8ebe0b6c97dfdceb0ad2fdeefJean Chalard final ArrayList<SuggestedWords.SuggestedWordInfo> typedWordAndPreviousSuggestions = 178188bf1ba5263f5a5c1df367ddc401db4109ef8677Jean Chalard SuggestedWords.getTypedWordAndPreviousSuggestions( 17824ee186920e642ae8ebe0b6c97dfdceb0ad2fdeefJean Chalard typedWord, previousSuggestions); 17837d55c891afdf7e74e505acac998a95a9ca7a9ec2Jean Chalard final SuggestedWords obsoleteSuggestedWords = 1784bdf6d1b18b3cebdde5f39d10066ead34be161bafJean Chalard new SuggestedWords(typedWordAndPreviousSuggestions, 17852e2519ee914d4bf9462950553840557a4c19faedJean Chalard false /* typedWordValid */, 1786bdf6d1b18b3cebdde5f39d10066ead34be161bafJean Chalard false /* hasAutoCorrectionCandidate */, 1787b5eeb724fc98bb7169683539027d9ba54ffb8b14Jean Chalard false /* allowsToBeAutoCorrected */, 178803a35170751a635332c00bf6c272a0127a255cf6Jean Chalard false /* isPunctuationSuggestions */, 17890142b997bf18f5d07e83b3fd403f0b3ea4736040satok true /* isObsoleteSuggestions */, 17900142b997bf18f5d07e83b3fd403f0b3ea4736040satok false /* isPrediction */); 17917d55c891afdf7e74e505acac998a95a9ca7a9ec2Jean Chalard showSuggestions(obsoleteSuggestedWords, typedWord); 17929fb8c6dd48dfa4e45827628a866d9b13c4c6c799Tadashi G. Takaoka } 1793979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 17944a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani 1795d992fa847da8f232d961ff097857757bfbff73a5Jean Chalard public void showSuggestions(final SuggestedWords suggestedWords, final CharSequence typedWord) { 1796d992fa847da8f232d961ff097857757bfbff73a5Jean Chalard final CharSequence autoCorrection; 17977e181fe1010c8eac7814cc67a0c4b3864a10b151Tadashi G. Takaoka if (suggestedWords.size() > 0) { 179868823ae08e820f0951447ed12c1bd32a24333d2eJean Chalard if (suggestedWords.hasAutoCorrectionWord()) { 1799d992fa847da8f232d961ff097857757bfbff73a5Jean Chalard autoCorrection = suggestedWords.getWord(1); 1800923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1801d992fa847da8f232d961ff097857757bfbff73a5Jean Chalard autoCorrection = typedWord; 1802923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1803923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } else { 1804d992fa847da8f232d961ff097857757bfbff73a5Jean Chalard autoCorrection = null; 1805923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1806d992fa847da8f232d961ff097857757bfbff73a5Jean Chalard mWordComposer.setAutoCorrection(autoCorrection); 18079b01890254c62a30b079bd9f79a30f9541faf11bJean Chalard final boolean isAutoCorrection = suggestedWords.willAutoCorrect(); 1808dd931c47be1a4fe4cf86c8ad018e479c2cbdf8ceJean Chalard setSuggestions(suggestedWords, isAutoCorrection); 1809dd931c47be1a4fe4cf86c8ad018e479c2cbdf8ceJean Chalard setAutoCorrectionIndicator(isAutoCorrection); 1810913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShown(isSuggestionsStripVisible()); 1811923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1812923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1813f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard private void commitCurrentAutoCorrection(final int separatorCodePoint, 1814f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard final InputConnection ic) { 1815913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka // Complete any pending suggestions query first 1816d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka if (mHandler.hasPendingUpdateSuggestions()) { 1817d7641636db8fe91d9847ac79f5f431963e876ec3Tadashi G. Takaoka mHandler.cancelUpdateSuggestions(); 1818923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project updateSuggestions(); 1819923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1820117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard final CharSequence autoCorrection = mWordComposer.getAutoCorrectionOrNull(); 1821117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard if (autoCorrection != null) { 1822117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard final String typedWord = mWordComposer.getTypedWord(); 182346798d8f1f3d9012433d000790ba30ba910c0fa0Jean Chalard if (TextUtils.isEmpty(typedWord)) { 182446798d8f1f3d9012433d000790ba30ba910c0fa0Jean Chalard throw new RuntimeException("We have an auto-correction but the typed word " 182546798d8f1f3d9012433d000790ba30ba910c0fa0Jean Chalard + "is empty? Impossible! I must commit suicide."); 182646798d8f1f3d9012433d000790ba30ba910c0fa0Jean Chalard } 1827f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard Utils.Stats.onAutoCorrection(typedWord, autoCorrection.toString(), separatorCodePoint); 182860adb8757496fecb8f376a80832c176b35e43d06Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 1829d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_commitCurrentAutoCorrection(typedWord, 183060adb8757496fecb8f376a80832c176b35e43d06Kurt Partridge autoCorrection.toString()); 183160adb8757496fecb8f376a80832c176b35e43d06Kurt Partridge } 18324733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 183366bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitChosenWord(autoCorrection, LastComposedWord.COMMIT_TYPE_DECIDED_WORD, 183466bb563535dbe3672f99f75bd71763a551444867Jean Chalard separatorCodePoint); 1835c24f66e18007b5aba32bfab8f86eb7f03fa6c1b7Jean Chalard // Add the word to the user history dictionary 1836c24f66e18007b5aba32bfab8f86eb7f03fa6c1b7Jean Chalard addToUserHistoryDictionary(autoCorrection); 1837f3ca6a59a7d6336fc318fe15467a1b447dc3ec4bJean Chalard if (!typedWord.equals(autoCorrection) && null != ic) { 18381c6cf26c3705e845418a29718c034598b52293ccJean Chalard // This will make the correction flash for a short while as a visual clue 18391c6cf26c3705e845418a29718c034598b52293ccJean Chalard // to the user that auto-correction happened. 184096fdc4dd8426a078500ce1d8a104bde7201bf9b5Ken Wakasa ic.commitCorrection(new CorrectionInfo(mLastSelectionEnd - typedWord.length(), 184196fdc4dd8426a078500ce1d8a104bde7201bf9b5Ken Wakasa typedWord, autoCorrection)); 18421c6cf26c3705e845418a29718c034598b52293ccJean Chalard } 1843923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1844923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1845923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1846c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka @Override 18479bfb6202154e06d7156f2f374dd9359f1be4eb68Kurt Partridge public void pickSuggestionManually(final int index, final CharSequence suggestion, 18489bfb6202154e06d7156f2f374dd9359f1be4eb68Kurt Partridge int x, int y) { 184996fb3094aaacf4bae65db54414a7aac285695245Jean Chalard final InputConnection ic = getCurrentInputConnection(); 1850d4cacb1e41263ea4d78e7328f9d7ee173b79c4eaJean Chalard if (null != ic) ic.beginBatchEdit(); 1851d4cacb1e41263ea4d78e7328f9d7ee173b79c4eaJean Chalard pickSuggestionManuallyWhileInBatchEdit(index, suggestion, x, y, ic); 1852d4cacb1e41263ea4d78e7328f9d7ee173b79c4eaJean Chalard if (null != ic) ic.endBatchEdit(); 1853d4cacb1e41263ea4d78e7328f9d7ee173b79c4eaJean Chalard } 18544f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett 1855d4cacb1e41263ea4d78e7328f9d7ee173b79c4eaJean Chalard public void pickSuggestionManuallyWhileInBatchEdit(final int index, 1856d4cacb1e41263ea4d78e7328f9d7ee173b79c4eaJean Chalard final CharSequence suggestion, final int x, final int y, final InputConnection ic) { 1857d4cacb1e41263ea4d78e7328f9d7ee173b79c4eaJean Chalard final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions(); 1858551612dd9ec79c9f9a7e430801fdf430dfe625e9Jean Chalard // If this is a punctuation picked from the suggestion strip, pass it to onCodeInput 1859551612dd9ec79c9f9a7e430801fdf430dfe625e9Jean Chalard if (suggestion.length() == 1 && isShowingPunctuationList()) { 1860551612dd9ec79c9f9a7e430801fdf430dfe625e9Jean Chalard // Word separators are suggested before the user inputs something. 1861551612dd9ec79c9f9a7e430801fdf430dfe625e9Jean Chalard // So, LatinImeLogger logs "" as a user's input. 1862551612dd9ec79c9f9a7e430801fdf430dfe625e9Jean Chalard LatinImeLogger.logOnManualSuggestion("", suggestion.toString(), index, suggestedWords); 1863551612dd9ec79c9f9a7e430801fdf430dfe625e9Jean Chalard // Rely on onCodeInput to do the complicated swapping/stripping logic consistently. 1864551612dd9ec79c9f9a7e430801fdf430dfe625e9Jean Chalard if (ProductionFlag.IS_EXPERIMENTAL) { 1865551612dd9ec79c9f9a7e430801fdf430dfe625e9Jean Chalard ResearchLogger.latinIME_punctuationSuggestion(index, suggestion, x, y); 1866551612dd9ec79c9f9a7e430801fdf430dfe625e9Jean Chalard } 1867551612dd9ec79c9f9a7e430801fdf430dfe625e9Jean Chalard final int primaryCode = suggestion.charAt(0); 1868551612dd9ec79c9f9a7e430801fdf430dfe625e9Jean Chalard onCodeInput(primaryCode, 1869551612dd9ec79c9f9a7e430801fdf430dfe625e9Jean Chalard KeyboardActionListener.SUGGESTION_STRIP_COORDINATE, 1870551612dd9ec79c9f9a7e430801fdf430dfe625e9Jean Chalard KeyboardActionListener.SUGGESTION_STRIP_COORDINATE); 1871551612dd9ec79c9f9a7e430801fdf430dfe625e9Jean Chalard return; 1872551612dd9ec79c9f9a7e430801fdf430dfe625e9Jean Chalard } 1873551612dd9ec79c9f9a7e430801fdf430dfe625e9Jean Chalard 1874845b24d9d31072b98958c557366617ad1c34f1b7Jean Chalard if (SPACE_STATE_PHANTOM == mSpaceState && suggestion.length() > 0) { 1875845b24d9d31072b98958c557366617ad1c34f1b7Jean Chalard int firstChar = Character.codePointAt(suggestion, 0); 1876845b24d9d31072b98958c557366617ad1c34f1b7Jean Chalard if ((!mSettingsValues.isWeakSpaceStripper(firstChar)) 1877845b24d9d31072b98958c557366617ad1c34f1b7Jean Chalard && (!mSettingsValues.isWeakSpaceSwapper(firstChar))) { 1878845b24d9d31072b98958c557366617ad1c34f1b7Jean Chalard sendKeyCodePoint(Keyboard.CODE_SPACE); 1879845b24d9d31072b98958c557366617ad1c34f1b7Jean Chalard } 1880845b24d9d31072b98958c557366617ad1c34f1b7Jean Chalard } 1881845b24d9d31072b98958c557366617ad1c34f1b7Jean Chalard 1882dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard if (mInputAttributes.mApplicationSpecifiedCompletionOn 1883dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard && mApplicationSpecifiedCompletions != null 18841b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka && index >= 0 && index < mApplicationSpecifiedCompletions.length) { 1885913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka if (mSuggestionsView != null) { 1886913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsView.clear(); 1887923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1888b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mKeyboardSwitcher.updateShiftState(); 1889611a5bdf650f7bc54bf40176f84f1cd9c87aa9aaJean Chalard resetComposingState(true /* alsoResetLastComposedWord */); 18909a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa if (ic != null) { 1891e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index]; 1892e771fc2f1ac7935befcc4d872cc974a47b50fdc7Jean Chalard ic.commitCompletion(completionInfo); 18939bfb6202154e06d7156f2f374dd9359f1be4eb68Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 18949bfb6202154e06d7156f2f374dd9359f1be4eb68Kurt Partridge ResearchLogger.latinIME_pickApplicationSpecifiedCompletion(index, 18959bfb6202154e06d7156f2f374dd9359f1be4eb68Kurt Partridge completionInfo.getText(), x, y); 18969bfb6202154e06d7156f2f374dd9359f1be4eb68Kurt Partridge } 18979a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa } 1898923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return; 1899923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 19006a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 1901af9fe5c5fcad1db22f605e0568c9a77cef178d22Jean Chalard // We need to log before we commit, because the word composer will store away the user 1902af9fe5c5fcad1db22f605e0568c9a77cef178d22Jean Chalard // typed word. 19039bfb6202154e06d7156f2f374dd9359f1be4eb68Kurt Partridge final String replacedWord = mWordComposer.getTypedWord().toString(); 19049bfb6202154e06d7156f2f374dd9359f1be4eb68Kurt Partridge LatinImeLogger.logOnManualSuggestion(replacedWord, 19058cc8f26adfe0f06cebc697dac43a856326cf7afcTadashi G. Takaoka suggestion.toString(), index, suggestedWords); 19069bfb6202154e06d7156f2f374dd9359f1be4eb68Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 19079bfb6202154e06d7156f2f374dd9359f1be4eb68Kurt Partridge ResearchLogger.latinIME_pickSuggestionManually(replacedWord, index, suggestion, x, y); 19089bfb6202154e06d7156f2f374dd9359f1be4eb68Kurt Partridge } 19094733609947c0ec74e460bd714fffca0518ade93aJean Chalard mExpectingUpdateSelection = true; 191066bb563535dbe3672f99f75bd71763a551444867Jean Chalard commitChosenWord(suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK, 191166bb563535dbe3672f99f75bd71763a551444867Jean Chalard LastComposedWord.NOT_A_SEPARATOR); 191229a1fc0f6b18dd41e7810ee720041f7c7557eb4fJean Chalard // Don't allow cancellation of manual pick 191329a1fc0f6b18dd41e7810ee720041f7c7557eb4fJean Chalard mLastComposedWord.deactivate(); 1914c24f66e18007b5aba32bfab8f86eb7f03fa6c1b7Jean Chalard // Add the word to the user history dictionary 1915c24f66e18007b5aba32bfab8f86eb7f03fa6c1b7Jean Chalard addToUserHistoryDictionary(suggestion); 1916fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard mSpaceState = SPACE_STATE_PHANTOM; 1917fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard // TODO: is this necessary? 1918fb684cebe8f5dac1bdb6cfa7085a07ddc66acedeJean Chalard mKeyboardSwitcher.updateShiftState(); 1919979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1920c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // We should show the "Touch again to save" hint if the user pressed the first entry 1921c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // AND either: 19227f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is no dictionary (we know that because we tried to load it => null != mSuggest 1923c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa // AND mSuggest.hasMainDictionary() is false) 19247f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // - There is a dictionary and the word is not in it 19257f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // Please note that if mSuggest is null, it means that everything is off: suggestion 19267f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // and correction, so we shouldn't try to show the hint 19277f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // We used to look at mCorrectionMode here, but showing the hint should have nothing 19287f2ba16aa2adba95e0575a2c6d58f6240154f313Jean Chalard // to do with the autocorrection setting. 1929bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok final boolean showingAddToDictionaryHint = index == 0 && mSuggest != null 1930bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // If there is no dictionary the hint should be shown. 1931c769ef4dd17ff9561e99528624f74b9072a09fbbKen Wakasa && (!mSuggest.hasMainDictionary() 1932bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok // If "suggestion" is not in the dictionary, the hint should be shown. 1933bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok || !AutoCorrection.isValidWord( 1934bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok mSuggest.getUnigramDictionaries(), suggestion, true)); 1935b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani 1936406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard Utils.Stats.onSeparator((char)Keyboard.CODE_SPACE, WordComposer.NOT_A_COORDINATE, 1937406d192a9e8f07ed6c6a408650feb0a757ca388eJean Chalard WordComposer.NOT_A_COORDINATE); 1938777118a40a363ccab69a00016d3156066513cb78Jean Chalard if (!showingAddToDictionaryHint) { 1939364da8c618303a7764595d2c15ee034a7671365dKen Wakasa // If we're not showing the "Touch again to save", then show corrections again. 1940979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // In case the cursor position doesn't change, make sure we show the suggestions again. 194141ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard updateBigramPredictions(); 194241ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // Updating the predictions right away may be slow and feel unresponsive on slower 194341ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // terminals. On the other hand if we just postUpdateBigramPredictions() it will 194441ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard // take a noticeable delay to update them which may feel uneasy. 194595a6e58ebcd8f44b970a8238cf30e48b10fc4b61Jean Chalard } else { 194688562bec54658840dcce352127bdc15705c20a89Jean Chalard if (mIsUserDictionaryAvailable) { 1947644d33d60ea5a87501274488013d65f55238895eKen Wakasa mSuggestionsView.showAddToDictionaryHint( 1948644d33d60ea5a87501274488013d65f55238895eKen Wakasa suggestion, mSettingsValues.mHintToSaveText); 1949ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka } else { 1950ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka mHandler.postUpdateSuggestions(); 1951ada26bb383f5b9de4717a980a3aa8f53d267df93Tadashi G. Takaoka } 195266a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani } 1953923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1954a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 1955979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 19568558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa * Commits the chosen word to the text field and saves it for later retrieval. 1957979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 195866bb563535dbe3672f99f75bd71763a551444867Jean Chalard private void commitChosenWord(final CharSequence bestWord, final int commitType, 195966bb563535dbe3672f99f75bd71763a551444867Jean Chalard final int separatorCode) { 19609351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 1961923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic != null) { 19621531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard if (mSettingsValues.mEnableSuggestionSpanInsertion) { 19631531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions(); 19641531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan( 19656a7019ff5db19b1e3f8d7afbba71af813cab9a37Tadashi G. Takaoka this, bestWord, suggestedWords, mIsMainDictionaryAvailable), 1966cf6b2099be5deda896ba129a835a06867be2293fsatok 1); 1967d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 1968d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_commitText(bestWord); 1969d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 19701531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard } else { 19711531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard ic.commitText(bestWord, 1); 1972d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 1973d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_commitText(bestWord); 1974d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 19751531528bfe01d0ce88888d23952a4c7092a15f17Jean Chalard } 1976923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 19770fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard // TODO: figure out here if this is an auto-correct or if the best word is actually 19780fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard // what user typed. Note: currently this is done much later in 1979bdf89ce5feedb03e67b43f530b1eb9bd44203c63Jean Chalard // LastComposedWord#didCommitTypedWord by string equality of the remembered 19800fd625bcfdfac1c10e7bd7f9088bf425fec08989Jean Chalard // strings. 198166bb563535dbe3672f99f75bd71763a551444867Jean Chalard mLastComposedWord = mWordComposer.commitWord(commitType, bestWord.toString(), 198266bb563535dbe3672f99f75bd71763a551444867Jean Chalard separatorCode); 1983923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1984923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 198541ec3ec2f3a95f0af2697da92cee4920e6156763Jean Chalard public void updateBigramPredictions() { 198689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (mSuggest == null || !isSuggestionsRequested()) 198789bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard return; 198889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 198917c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard if (!mSettingsValues.mBigramPredictionEnabled) { 1990cb3320179d39a7983874697a0aa428b127675c9dJean Chalard setPunctuationSuggestions(); 1991cb3320179d39a7983874697a0aa428b127675c9dJean Chalard return; 1992cb3320179d39a7983874697a0aa428b127675c9dJean Chalard } 1993cb3320179d39a7983874697a0aa428b127675c9dJean Chalard 19948e19b1183e4925b7c396de45a5e4e7d67a7b876aJean Chalard final SuggestedWords suggestedWords; 1995a333ff19ef330c93287cfa0f6568d0cdcd431b04Jean Chalard if (mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { 1996a333ff19ef330c93287cfa0f6568d0cdcd431b04Jean Chalard final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(), 1997a333ff19ef330c93287cfa0f6568d0cdcd431b04Jean Chalard mSettingsValues.mWordSeparators); 19980cf422fbb763e2672fb2f9e8e1e8af91d2e87cb3Jean Chalard if (!TextUtils.isEmpty(prevWord)) { 19995b0643f50d8c363296360f3ceaf32f7edc157141Jean Chalard suggestedWords = mSuggest.getBigramPredictions(prevWord); 20000cf422fbb763e2672fb2f9e8e1e8af91d2e87cb3Jean Chalard } else { 20018e19b1183e4925b7c396de45a5e4e7d67a7b876aJean Chalard suggestedWords = null; 20020cf422fbb763e2672fb2f9e8e1e8af91d2e87cb3Jean Chalard } 2003a333ff19ef330c93287cfa0f6568d0cdcd431b04Jean Chalard } else { 20048e19b1183e4925b7c396de45a5e4e7d67a7b876aJean Chalard suggestedWords = null; 2005a333ff19ef330c93287cfa0f6568d0cdcd431b04Jean Chalard } 200689bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 20078e19b1183e4925b7c396de45a5e4e7d67a7b876aJean Chalard if (null != suggestedWords && suggestedWords.size() > 0) { 200889bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Explicitly supply an empty typed word (the no-second-arg version of 200989bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // showSuggestions will retrieve the word near the cursor, we don't want that here) 20108e19b1183e4925b7c396de45a5e4e7d67a7b876aJean Chalard showSuggestions(suggestedWords, ""); 201189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } else { 201289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (!isShowingPunctuationList()) setPunctuationSuggestions(); 201389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 201489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 201589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard 20167a8dac55278cedd838be325f56b4c52d973c61f5satok public void setPunctuationSuggestions() { 2017dd931c47be1a4fe4cf86c8ad018e479c2cbdf8ceJean Chalard setSuggestions(mSettingsValues.mSuggestPuncList, false); 20187204eab3da916d8873b7eeee4b4528a6b82de19cJean Chalard setAutoCorrectionIndicator(false); 2019913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka setSuggestionStripShown(isSuggestionsStripVisible()); 20206a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani } 20216a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 2022c24f66e18007b5aba32bfab8f86eb7f03fa6c1b7Jean Chalard private void addToUserHistoryDictionary(final CharSequence suggestion) { 20233ee7d97587ccbbeb8003d2142478337e8d60b2b7Jean Chalard if (TextUtils.isEmpty(suggestion)) return; 2024bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok 20250c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be 20260c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // adding words in situations where the user or application really didn't 20270c05902e331b03426754a1cfffe28d185dd8338cAmith Yamasani // want corrections enabled or learned. 2028979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (!(mCorrectionMode == Suggest.CORRECTION_FULL 2029979f8690967ff5409fe18f5085858ccdb8e0ccf1satok || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) { 2030979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return; 2031979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 2032bcfce3b3b9dbd4f5db736948b74bd820fc639a08satok 20339ffb94fa1318f354692fab7abf4775fa14397a96Jean Chalard if (mUserHistoryDictionary != null) { 203440f7efc172928bdd6048e91421a766abe5b22996Jean Chalard final InputConnection ic = getCurrentInputConnection(); 20359ffb94fa1318f354692fab7abf4775fa14397a96Jean Chalard final CharSequence prevWord; 203640f7efc172928bdd6048e91421a766abe5b22996Jean Chalard if (null != ic) { 20379ffb94fa1318f354692fab7abf4775fa14397a96Jean Chalard prevWord = EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators); 20389ffb94fa1318f354692fab7abf4775fa14397a96Jean Chalard } else { 20399ffb94fa1318f354692fab7abf4775fa14397a96Jean Chalard prevWord = null; 2040979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 204171f9d30b18e05d7d97d607d1aac3f81c6724abd9Jean Chalard final String secondWord; 204271f9d30b18e05d7d97d607d1aac3f81c6724abd9Jean Chalard if (mWordComposer.isAutoCapitalized() && !mWordComposer.isMostlyCaps()) { 20436a7019ff5db19b1e3f8d7afbba71af813cab9a37Tadashi G. Takaoka secondWord = suggestion.toString().toLowerCase( 20446a7019ff5db19b1e3f8d7afbba71af813cab9a37Tadashi G. Takaoka mSubtypeSwitcher.getCurrentSubtypeLocale()); 204571f9d30b18e05d7d97d607d1aac3f81c6724abd9Jean Chalard } else { 204671f9d30b18e05d7d97d607d1aac3f81c6724abd9Jean Chalard secondWord = suggestion.toString(); 204771f9d30b18e05d7d97d607d1aac3f81c6724abd9Jean Chalard } 20489ffb94fa1318f354692fab7abf4775fa14397a96Jean Chalard mUserHistoryDictionary.addToUserHistory(null == prevWord ? null : prevWord.toString(), 204971f9d30b18e05d7d97d607d1aac3f81c6724abd9Jean Chalard secondWord); 205032e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 205132e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani } 205232e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani 20537a8dac55278cedd838be325f56b4c52d973c61f5satok public boolean isCursorTouchingWord() { 20549351550dc6af7859e5280e16144c9386a37b976dKen Wakasa final InputConnection ic = getCurrentInputConnection(); 2055923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (ic == null) return false; 20568667bbeab3321e05f518770f7360a3fef52b4407Jean Chalard CharSequence before = ic.getTextBeforeCursor(1, 0); 20578667bbeab3321e05f518770f7360a3fef52b4407Jean Chalard CharSequence after = ic.getTextAfterCursor(1, 0); 20586ec1209a33fe2dc151b86d3f662e22e564e2f4f8Jean Chalard if (!TextUtils.isEmpty(before) && !mSettingsValues.isWordSeparator(before.charAt(0)) 20596ec1209a33fe2dc151b86d3f662e22e564e2f4f8Jean Chalard && !mSettingsValues.isSymbolExcludedFromWordSeparators(before.charAt(0))) { 2060923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 2061923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 20626ec1209a33fe2dc151b86d3f662e22e564e2f4f8Jean Chalard if (!TextUtils.isEmpty(after) && !mSettingsValues.isWordSeparator(after.charAt(0)) 20636ec1209a33fe2dc151b86d3f662e22e564e2f4f8Jean Chalard && !mSettingsValues.isSymbolExcludedFromWordSeparators(after.charAt(0))) { 2064923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return true; 2065923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2066923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return false; 2067923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2068a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2069120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // "ic" must not be null 20708ff0564f6a7c78e2fda517ea49b2ac2fa96d0f8eJean Chalard private static boolean sameAsTextBeforeCursor(final InputConnection ic, 20718ff0564f6a7c78e2fda517ea49b2ac2fa96d0f8eJean Chalard final CharSequence text) { 20728ff0564f6a7c78e2fda517ea49b2ac2fa96d0f8eJean Chalard final CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0); 2073dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani return TextUtils.equals(text, beforeText); 2074dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani } 2075dad0e792aa064765901224af56d2a53a25bc7b7dAmith Yamasani 2076120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // "ic" must not be null 20776b1f500da451de56932a8b2a99c63857994ece85Jean Chalard /** 20786b1f500da451de56932a8b2a99c63857994ece85Jean Chalard * Check if the cursor is actually at the end of a word. If so, restart suggestions on this 20796b1f500da451de56932a8b2a99c63857994ece85Jean Chalard * word, else do nothing. 20806b1f500da451de56932a8b2a99c63857994ece85Jean Chalard */ 20816b1f500da451de56932a8b2a99c63857994ece85Jean Chalard private void restartSuggestionsOnWordBeforeCursorIfAtEndOfWord( 20826b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final InputConnection ic) { 20836b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Bail out if the cursor is not at the end of a word (cursor must be preceded by 20846b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // non-whitespace, non-separator, non-start-of-text) 20856b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Example ("|" is the cursor here) : <SOL>"|a" " |a" " | " all get rejected here. 20866b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final CharSequence textBeforeCursor = ic.getTextBeforeCursor(1, 0); 20876b1f500da451de56932a8b2a99c63857994ece85Jean Chalard if (TextUtils.isEmpty(textBeforeCursor) 20886b1f500da451de56932a8b2a99c63857994ece85Jean Chalard || mSettingsValues.isWordSeparator(textBeforeCursor.charAt(0))) return; 20896b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 20906b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Bail out if the cursor is in the middle of a word (cursor must be followed by whitespace, 20916b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // separator or end of line/text) 20926b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Example: "test|"<EOL> "te|st" get rejected here 20936b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final CharSequence textAfterCursor = ic.getTextAfterCursor(1, 0); 20946b1f500da451de56932a8b2a99c63857994ece85Jean Chalard if (!TextUtils.isEmpty(textAfterCursor) 20956b1f500da451de56932a8b2a99c63857994ece85Jean Chalard && !mSettingsValues.isWordSeparator(textAfterCursor.charAt(0))) return; 20966b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 20976b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Bail out if word before cursor is 0-length or a single non letter (like an apostrophe) 2098fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // Example: " -|" gets rejected here but "e-|" and "e|" are okay 2099fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard CharSequence word = EditingUtils.getWordAtCursor(ic, mSettingsValues.mWordSeparators); 2100fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // We don't suggest on leading single quotes, so we have to remove them from the word if 2101fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // it starts with single quotes. 2102fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard while (!TextUtils.isEmpty(word) && Keyboard.CODE_SINGLE_QUOTE == word.charAt(0)) { 2103fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard word = word.subSequence(1, word.length()); 2104fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard } 21056b1f500da451de56932a8b2a99c63857994ece85Jean Chalard if (TextUtils.isEmpty(word)) return; 2106fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard final char firstChar = word.charAt(0); // we just tested that word is not empty 2107fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard if (word.length() == 1 && !Character.isLetter(firstChar)) return; 2108fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard 2109fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // We only suggest on words that start with a letter or a symbol that is excluded from 2110fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard // word separators (see #handleCharacterWhileInBatchEdit). 2111fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard if (!(isAlphabet(firstChar) 2112fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard || mSettingsValues.isSymbolExcludedFromWordSeparators(firstChar))) { 2113fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard return; 2114fbd1ac80838abb47bca25203f05de3a364356f27Jean Chalard } 21156b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 21166b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // Okay, we are at the end of a word. Restart suggestions. 21176b1f500da451de56932a8b2a99c63857994ece85Jean Chalard restartSuggestionsOnWordBeforeCursor(ic, word); 21186b1f500da451de56932a8b2a99c63857994ece85Jean Chalard } 21196b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 21206b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // "ic" must not be null 21216b1f500da451de56932a8b2a99c63857994ece85Jean Chalard private void restartSuggestionsOnWordBeforeCursor(final InputConnection ic, 21226b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final CharSequence word) { 21233708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka mWordComposer.setComposingWord(word, mKeyboardSwitcher.getKeyboard()); 2124d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge final int length = word.length(); 2125d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ic.deleteSurroundingText(length, 0); 2126d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 2127d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_deleteSurroundingText(length); 2128d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 21296b1f500da451de56932a8b2a99c63857994ece85Jean Chalard ic.setComposingText(word, 1); 21306b1f500da451de56932a8b2a99c63857994ece85Jean Chalard mHandler.postUpdateSuggestions(); 21316b1f500da451de56932a8b2a99c63857994ece85Jean Chalard } 21326b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 21336b1f500da451de56932a8b2a99c63857994ece85Jean Chalard // "ic" must not be null 21345935950d4431dd7eef18ebc370f2abeb614465d4Jean Chalard private void revertCommit(final InputConnection ic) { 2135b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard final String originallyTypedWord = mLastComposedWord.mTypedWord; 2136cf9d92629cae88273805eaf7984fcfdd8afd11f5Jean Chalard final CharSequence committedWord = mLastComposedWord.mCommittedWord; 2137cf9d92629cae88273805eaf7984fcfdd8afd11f5Jean Chalard final int cancelLength = committedWord.length(); 2138ca7ec2097ca6af1505c1e6aa8b81b6068ba46daesatok final int separatorLength = LastComposedWord.getSeparatorLength( 2139193d23f40e1556074f323b7bd9695759f4798efeJean Chalard mLastComposedWord.mSeparatorCode); 2140193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // TODO: should we check our saved separator against the actual contents of the text view? 2141d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge final int deleteLength = cancelLength + separatorLength; 2142890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard if (DEBUG) { 2143b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard if (mWordComposer.isComposingWord()) { 21445935950d4431dd7eef18ebc370f2abeb614465d4Jean Chalard throw new RuntimeException("revertCommit, but we are composing a word"); 2145b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard } 2146890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard final String wordBeforeCursor = 2147d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ic.getTextBeforeCursor(deleteLength, 0) 2148193d23f40e1556074f323b7bd9695759f4798efeJean Chalard .subSequence(0, cancelLength).toString(); 2149cf9d92629cae88273805eaf7984fcfdd8afd11f5Jean Chalard if (!TextUtils.equals(committedWord, wordBeforeCursor)) { 21505935950d4431dd7eef18ebc370f2abeb614465d4Jean Chalard throw new RuntimeException("revertCommit check failed: we thought we were " 2151cf9d92629cae88273805eaf7984fcfdd8afd11f5Jean Chalard + "reverting \"" + committedWord 2152890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard + "\", but before the cursor we found \"" + wordBeforeCursor + "\""); 2153890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard } 21548558cfb42a412010f2e5320ee50fe44afefdc1cfKen Wakasa } 2155d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ic.deleteSurroundingText(deleteLength, 0); 2156d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 2157d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_deleteSurroundingText(deleteLength); 2158d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 2159193d23f40e1556074f323b7bd9695759f4798efeJean Chalard if (0 == separatorLength || mLastComposedWord.didCommitTypedWord()) { 2160193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // This is the case when we cancel a manual pick. 2161193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // We should restart suggestion on the word right away. 216232f0af1fc48f67907f0e731e18359f29e2b1df14Jean Chalard mWordComposer.resumeSuggestionOnLastComposedWord(mLastComposedWord); 216332f0af1fc48f67907f0e731e18359f29e2b1df14Jean Chalard ic.setComposingText(originallyTypedWord, 1); 2164193d23f40e1556074f323b7bd9695759f4798efeJean Chalard } else { 2165193d23f40e1556074f323b7bd9695759f4798efeJean Chalard ic.commitText(originallyTypedWord, 1); 2166193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // Re-insert the separator 2167193d23f40e1556074f323b7bd9695759f4798efeJean Chalard sendKeyCodePoint(mLastComposedWord.mSeparatorCode); 2168193d23f40e1556074f323b7bd9695759f4798efeJean Chalard Utils.Stats.onSeparator(mLastComposedWord.mSeparatorCode, WordComposer.NOT_A_COORDINATE, 2169193d23f40e1556074f323b7bd9695759f4798efeJean Chalard WordComposer.NOT_A_COORDINATE); 2170d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 2171d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_revertCommit(originallyTypedWord); 2172d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 2173193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // Don't restart suggestion yet. We'll restart if the user deletes the 2174193d23f40e1556074f323b7bd9695759f4798efeJean Chalard // separator. 2175193d23f40e1556074f323b7bd9695759f4798efeJean Chalard } 2176b6b8729374dc68b153f00730c79828532acf1ee5Jean Chalard mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; 2177890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard mHandler.cancelUpdateBigramPredictions(); 2178890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard mHandler.postUpdateSuggestions(); 2179890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard } 2180890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard 2181890d13189d8dd305681bcb00d09f34d3ae68c648Jean Chalard // "ic" must not be null 21822124bc5bf5af31cf3d2789b70ebd2f24c815f5f4Jean Chalard private boolean revertDoubleSpaceWhileInBatchEdit(final InputConnection ic) { 21834733609947c0ec74e460bd714fffca0518ade93aJean Chalard mHandler.cancelDoubleSpacesTimer(); 21844733609947c0ec74e460bd714fffca0518ade93aJean Chalard // Here we test whether we indeed have a period and a space before us. This should not 21854733609947c0ec74e460bd714fffca0518ade93aJean Chalard // be needed, but it's there just in case something went wrong. 21864733609947c0ec74e460bd714fffca0518ade93aJean Chalard final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0); 21878ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard if (!". ".equals(textBeforeCursor)) { 218851fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard // Theoretically we should not be coming here if there isn't ". " before the 218951fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard // cursor, but the application may be changing the text while we are typing, so 219051fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard // anything goes. We should not crash. 219151fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard Log.d(TAG, "Tried to revert double-space combo but we didn't find " 21928ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard + "\". \" just before the cursor."); 219351fd1632f59bd9aaeb5c98ff031f1618e8c31c59Jean Chalard return false; 21948ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard } 21954733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.deleteSurroundingText(2, 0); 2196d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 2197d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_deleteSurroundingText(2); 2198d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 21994733609947c0ec74e460bd714fffca0518ade93aJean Chalard ic.commitText(" ", 1); 2200d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 2201d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_revertDoubleSpaceWhileInBatchEdit(); 2202d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 22034733609947c0ec74e460bd714fffca0518ade93aJean Chalard return true; 22044733609947c0ec74e460bd714fffca0518ade93aJean Chalard } 22054733609947c0ec74e460bd714fffca0518ade93aJean Chalard 22068fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka private static boolean revertSwapPunctuation(final InputConnection ic) { 2207120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // Here we test whether we indeed have a space and something else before us. This should not 2208120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // be needed, but it's there just in case something went wrong. 2209120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0); 2210120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // NOTE: This does not work with surrogate pairs. Hopefully when the keyboard is able to 2211120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard // enter surrogate pairs this code will have been removed. 22128be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard if (TextUtils.isEmpty(textBeforeCursor) 22138be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard || (Keyboard.CODE_SPACE != textBeforeCursor.charAt(1))) { 22148be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard // We may only come here if the application is changing the text while we are typing. 22158be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard // This is quite a broken case, but not logically impossible, so we shouldn't crash, 22168be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard // but some debugging log may be in order. 22178be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard Log.d(TAG, "Tried to revert a swap of punctuation but we didn't " 22188ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard + "find a space just before the cursor."); 22198be16f78b10aa4a8975c4068db1b32f81f661a2cJean Chalard return false; 22208ad4013406e5e94967bb74baae3b068187f62e4bJean Chalard } 2221120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.beginBatchEdit(); 2222120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.deleteSurroundingText(2, 0); 2223d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 2224d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_deleteSurroundingText(2); 2225d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 2226120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.commitText(" " + textBeforeCursor.subSequence(0, 1), 1); 2227d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge if (ProductionFlag.IS_EXPERIMENTAL) { 2228d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge ResearchLogger.latinIME_revertSwapPunctuation(); 2229d442984e96cc6299c905141e3e32e0a4f55394c8Kurt Partridge } 2230120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard ic.endBatchEdit(); 2231120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard return true; 2232120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard } 2233120586c226c416d2211b6ebb3f4b914a30f9a74fJean Chalard 2234923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean isWordSeparator(int code) { 223517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard return mSettingsValues.isWordSeparator(code); 2236923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2237923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2238923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean preferCapitalization() { 22399318d33b6e501d4dd9ea860de04160ccb23a7501Ken Wakasa return mWordComposer.isFirstCharCapitalized(); 2240923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2241923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 224288fc9d44186120f9edc5cf7ec0e2af85260fed04satok // Notify that language or mode have been changed and toggleLanguage will update KeyboardID 2243c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka // according to new language or mode. 2244c1c4ee6b3a8c3ec42edefe42fd183f3cbf67b0bfTadashi G. Takaoka public void onRefreshKeyboard() { 22451e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka // When the device locale is changed in SetupWizard etc., this method may get called via 22461e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka // onConfigurationChanged before SoftInputWindow is shown. 22471e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka if (mKeyboardSwitcher.getKeyboardView() != null) { 22481e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka // Reload keyboard because the current language has been changed. 22491e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettingsValues); 22501e39565bb48d23221145c494d4bf5665b514699dTadashi G. Takaoka } 22510ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok initSuggest(); 22523fe263fac6375836c48ce71da29f098b66eb4f11Jean Chalard updateCorrectionMode(); 225317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard loadSettings(); 2254b84ee82e66d608151fcf552c82e7765a74e47fb0Jean Chalard // Since we just changed languages, we should re-evaluate suggestions with whatever word 2255b84ee82e66d608151fcf552c82e7765a74e47fb0Jean Chalard // we are currently composing. If we are not composing anything, we may want to display 2256b84ee82e66d608151fcf552c82e7765a74e47fb0Jean Chalard // predictions or punctuation signs (which is done by updateBigramPredictions anyway). 2257b84ee82e66d608151fcf552c82e7765a74e47fb0Jean Chalard if (isCursorTouchingWord()) { 2258b84ee82e66d608151fcf552c82e7765a74e47fb0Jean Chalard mHandler.postUpdateSuggestions(); 2259b84ee82e66d608151fcf552c82e7765a74e47fb0Jean Chalard } else { 2260b84ee82e66d608151fcf552c82e7765a74e47fb0Jean Chalard mHandler.postUpdateBigramPredictions(); 2261b84ee82e66d608151fcf552c82e7765a74e47fb0Jean Chalard } 226236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani } 226336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 226478e3977e90a9946a057dfb628f99683e386015bdTadashi G. Takaoka // TODO: Remove this method from {@link LatinIME} and move {@link FeedbackManager} to 226578e3977e90a9946a057dfb628f99683e386015bdTadashi G. Takaoka // {@link KeyboardSwitcher}. 2266564496bad6207f02e7a653872213bc5954e84ce4Jean Chalard public void hapticAndAudioFeedback(final int primaryCode) { 2267544c3c29527927239a6484efc30bc22f9cc4dad1Jean Chalard mFeedbackManager.hapticAndAudioFeedback(primaryCode, mKeyboardSwitcher.getKeyboardView()); 2268d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka } 2269d999ea44805ae0a3ccac4c4f49aaf500f6c479acTadashi G. Takaoka 22705a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 22712a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka public void onPressKey(int primaryCode) { 2272a5c96f376ad57e78a88942bb618e067054ed818aTadashi G. Takaoka mKeyboardSwitcher.onPressKey(primaryCode); 2273923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2274923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 22755a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka @Override 22762a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka public void onReleaseKey(int primaryCode, boolean withSliding) { 22772a88440419f49d100c73e067a823390f64aba3b1Tadashi G. Takaoka mKeyboardSwitcher.onReleaseKey(primaryCode, withSliding); 22788d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv 22798d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv // If accessibility is on, ensure the user receives keyboard state updates. 22808d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) { 22818d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv switch (primaryCode) { 22828d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case Keyboard.CODE_SHIFT: 22838d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv AccessibleKeyboardViewProxy.getInstance().notifyShiftState(); 22848d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv break; 22858d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: 22868d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv AccessibleKeyboardViewProxy.getInstance().notifySymbolsState(); 22878d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv break; 22888d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv } 22898d4f0d5d1df2e0ae0b6ac332fd6661b7fa903186alanv } 2290923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2291a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2292123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka // receive ringer mode change and network state change. 2293923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private BroadcastReceiver mReceiver = new BroadcastReceiver() { 2294923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 2295923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void onReceive(Context context, Intent intent) { 2296123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka final String action = intent.getAction(); 2297564496bad6207f02e7a653872213bc5954e84ce4Jean Chalard if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 2298123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka mSubtypeSwitcher.onNetworkStateChanged(intent); 229921af2f40c59de3ea5ec183aa278406bf28d5e3bdJean Chalard } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { 230021af2f40c59de3ea5ec183aa278406bf28d5e3bdJean Chalard mFeedbackManager.onRingerModeChanged(); 2301123c4a38514c003aac50caed7ad3cb6ab8f2515aTadashi G. Takaoka } 2302923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2303923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project }; 2304923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2305e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani private void updateCorrectionMode() { 23069f67e12a0e3f77985fb8bafe0db4c00e32317b9asatok // TODO: cleanup messy flags 2307f50aa193377492e9c4afb3cc6e7f3448ab5a97a4Jean Chalard final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled 2308dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard && !mInputAttributes.mInputTypeNoAutoCorrect; 2309283b0c2b642030539ba3e41f3f54b6aed6bb9e2dJean Chalard mCorrectionMode = shouldAutoCorrect ? Suggest.CORRECTION_FULL : Suggest.CORRECTION_NONE; 2310283b0c2b642030539ba3e41f3f54b6aed6bb9e2dJean Chalard mCorrectionMode = (mSettingsValues.mBigramSuggestionEnabled && shouldAutoCorrect) 2311979f8690967ff5409fe18f5085858ccdb8e0ccf1satok ? Suggest.CORRECTION_FULL_BIGRAM : mCorrectionMode; 2312e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani } 2313e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani 23142ac5988f84b5c38d313951a3d7faddebf5f25e04Tadashi G. Takaoka private void updateSuggestionVisibility(final Resources res) { 23150fe3611bee5095e7bd0fff2d0fdf8d5a13379132Jean Chalard final String suggestionVisiblityStr = mSettingsValues.mShowSuggestionsSetting; 23167599cfea4a2d56f4779452ec8e8742f7b9629cc0satok for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) { 2317458249e703bded3a1cbd25a2ab2249f9366a8188Ken Wakasa if (suggestionVisiblityStr.equals(res.getString(visibility))) { 23187599cfea4a2d56f4779452ec8e8742f7b9629cc0satok mSuggestionVisibility = visibility; 23197599cfea4a2d56f4779452ec8e8742f7b9629cc0satok break; 23207599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 23217599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 23227599cfea4a2d56f4779452ec8e8742f7b9629cc0satok } 23237599cfea4a2d56f4779452ec8e8742f7b9629cc0satok 2324c206d0462354b3bf1ad0cec61534da567829555dTadashi G. Takaoka private void launchSettings() { 2325c206d0462354b3bf1ad0cec61534da567829555dTadashi G. Takaoka launchSettingsClass(SettingsActivity.class); 2326466741d8a78965b8509bf527344f289e50873092Mike LeBeau } 2327466741d8a78965b8509bf527344f289e50873092Mike LeBeau 2328bf96661d33d0126adb60a48880ceba1ff055d4a4satok public void launchDebugSettings() { 2329c206d0462354b3bf1ad0cec61534da567829555dTadashi G. Takaoka launchSettingsClass(DebugSettingsActivity.class); 2330bf96661d33d0126adb60a48880ceba1ff055d4a4satok } 2331bf96661d33d0126adb60a48880ceba1ff055d4a4satok 2332c206d0462354b3bf1ad0cec61534da567829555dTadashi G. Takaoka private void launchSettingsClass(Class<? extends PreferenceActivity> settingsClass) { 2333923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project handleClose(); 2334923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project Intent intent = new Intent(); 2335466741d8a78965b8509bf527344f289e50873092Mike LeBeau intent.setClass(LatinIME.this, settingsClass); 2336923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2337923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project startActivity(intent); 2338923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2339923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 23402fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka private void showSubtypeSelectorAndSettings() { 234185996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence title = getString(R.string.english_ime_input_options); 234285996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final CharSequence[] items = new CharSequence[] { 234385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka // TODO: Should use new string "Select active input modes". 234485996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.language_selection_title), 234585996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka getString(R.string.english_ime_settings), 234685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 234755d28fd1b2631a63542a647f693d8a8ed749bcf7Tadashi G. Takaoka final Context context = this; 234885996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 23492fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka @Override 23502fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka public void onClick(DialogInterface di, int position) { 23512fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka di.dismiss(); 23522fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka switch (position) { 235385996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka case 0: 23542cff4d7e4abdb192151f9b4027fc93fe28a8bdaasatok Intent intent = CompatUtils.getInputLanguageSelectionIntent( 235555d28fd1b2631a63542a647f693d8a8ed749bcf7Tadashi G. Takaoka ImfUtils.getInputMethodIdOfThisIme(context), 23562a659b8aa642b0832fa0ac9a93e0640592fcc239Jean Chalard Intent.FLAG_ACTIVITY_NEW_TASK 23572fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 23582fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka | Intent.FLAG_ACTIVITY_CLEAR_TOP); 23592fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka startActivity(intent); 23602fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka break; 2361aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa case 1: 2362aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa launchSettings(); 2363aa0458f917bb823efab6245f08c65e8f2f7327acKen Wakasa break; 23642fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 23652fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 236685996b472a0ec5fc31e57c52aa46c8c7794689bbTadashi G. Takaoka }; 2367bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka final AlertDialog.Builder builder = new AlertDialog.Builder(this) 2368bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setItems(items, listener) 2369bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka .setTitle(title); 2370bf9d8348d89be257ccc3db75333bfd4cdf0a9b7eTadashi G. Takaoka showOptionDialogInternal(builder.create()); 23712fa21f5854e1565deb139e0bf22719fecc5340bcTadashi G. Takaoka } 2372923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 237313d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka private void showOptionDialogInternal(AlertDialog dialog) { 23746a7019ff5db19b1e3f8d7afbba71af813cab9a37Tadashi G. Takaoka final IBinder windowToken = mKeyboardSwitcher.getKeyboardView().getWindowToken(); 237513d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka if (windowToken == null) return; 237613d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka 237713d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka dialog.setCancelable(true); 237813d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka dialog.setCanceledOnTouchOutside(true); 237913d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka 238013d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka final Window window = dialog.getWindow(); 238113d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka final WindowManager.LayoutParams lp = window.getAttributes(); 238213d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka lp.token = windowToken; 238313d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 238413d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka window.setAttributes(lp); 238513d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 238613d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka 238713d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka mOptionsDialog = dialog; 238813d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka dialog.show(); 238913d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka } 239013d6ecc4c275b9e9c38c7713bb2c69d37f3467f3Tadashi G. Takaoka 23917e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka @Override 23927e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 2393923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project super.dump(fd, fout, args); 2394a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker 2395923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final Printer p = new PrintWriterPrinter(fout); 2396923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println("LatinIME state :"); 23973708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); 2398df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka final int keyboardMode = keyboard != null ? keyboard.mId.mMode : -1; 2399df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka p.println(" Keyboard mode = " + keyboardMode); 2400dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard p.println(" mIsSuggestionsRequested=" + mInputAttributes.mIsSettingsSuggestionStripOn); 2401923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project p.println(" mCorrectionMode=" + mCorrectionMode); 24024d0f03bd66742ee292da81a3e025e119f28b6940Jean Chalard p.println(" isComposingWord=" + mWordComposer.isComposingWord()); 240317c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mAutoCorrectEnabled=" + mSettingsValues.mAutoCorrectEnabled); 240417c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mSoundOn=" + mSettingsValues.mSoundOn); 240517c7ffeb1e10348227c5dff1c319d2099c1b5d0eJean Chalard p.println(" mVibrateOn=" + mSettingsValues.mVibrateOn); 2406240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard p.println(" mKeyPreviewPopupOn=" + mSettingsValues.mKeyPreviewPopupOn); 24076fa003ee234c6e2ca6cd9ec555221ac5c71a5405Jean Chalard p.println(" mInputAttributes=" + mInputAttributes.toString()); 2408923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2409923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 2410