KeyboardSwitcher.java revision f3cd2bb33d1688fd6de01787140a1ef2de4b7723
1923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/* 2443c360d0afdbab091994244f045f4756feaf2b4Jean-Baptiste Queru * Copyright (C) 2008 The Android Open Source Project 3571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka * 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 7571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka * 8923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka * 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 17571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokapackage com.android.inputmethod.keyboard; 18923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 19c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.content.Context; 20c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.content.SharedPreferences; 21c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.content.res.Resources; 22c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.util.Log; 23c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.view.InflateException; 24c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.view.LayoutInflater; 25c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.view.View; 26c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.view.inputmethod.EditorInfo; 27c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka 28610f1dc8553cf2ed97e763a06a19380c4a6cd636satokimport com.android.inputmethod.compat.InputMethodManagerCompatWrapper; 29571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.LatinIME; 30571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.LatinImeLogger; 31571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.R; 325cd87e1b1c4258e8d016518914eccfbb4437caceTadashi G. Takaokaimport com.android.inputmethod.latin.Settings; 33571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.SubtypeSwitcher; 345cd87e1b1c4258e8d016518914eccfbb4437caceTadashi G. Takaokaimport com.android.inputmethod.latin.Utils; 355a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka 36681b676b0aecb30e644f25550018ce2b6cea3e15Tadashi G. Takaokaimport java.lang.ref.SoftReference; 3712659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaokaimport java.util.HashMap; 3812659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaokaimport java.util.Locale; 3912659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaoka 40979f8690967ff5409fe18f5085858ccdb8e0ccf1satokpublic class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener { 418b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka private static final String TAG = "KeyboardSwitcher"; 42e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka private static final boolean DEBUG_CACHE = false; 43f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka public static final boolean DEBUG_STATE = false; 44923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 4505ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka private static String sConfigDefaultKeyboardThemeId; 46a327485e595c9f7676989097c830ff452085d4c9satok public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902"; 4705ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka private static final int[] KEYBOARD_THEMES = { 4875fde6489039c09056fb5e64d39630ece5ad57cfTadashi G. Takaoka R.layout.input_basic, 4975fde6489039c09056fb5e64d39630ece5ad57cfTadashi G. Takaoka R.layout.input_basic_highcontrast, 5075fde6489039c09056fb5e64d39630ece5ad57cfTadashi G. Takaoka R.layout.input_stone_normal, 5175fde6489039c09056fb5e64d39630ece5ad57cfTadashi G. Takaoka R.layout.input_stone_bold, 5275fde6489039c09056fb5e64d39630ece5ad57cfTadashi G. Takaoka R.layout.input_gingerbread, 5305ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka R.layout.input_honeycomb, 5475fde6489039c09056fb5e64d39630ece5ad57cfTadashi G. Takaoka }; 55979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 560ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private SubtypeSwitcher mSubtypeSwitcher; 5727d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa private SharedPreferences mPrefs; 580ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok 59c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka private LatinKeyboardView mKeyboardView; 600ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private LatinIME mInputMethodService; 6131adfa78e2edae188edb05e869f9f68798857582satok 62717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // TODO: Combine these key state objects with auto mode switch state. 63f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift"); 64f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol"); 65889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka 66353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger private KeyboardId mSymbolsId; 67353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger private KeyboardId mSymbolsShiftedId; 68353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger 69353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger private KeyboardId mCurrentId; 708b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache = 718b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka new HashMap<KeyboardId, SoftReference<LatinKeyboard>>(); 72466741d8a78965b8509bf527344f289e50873092Mike LeBeau 734b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka private EditorInfo mAttribute; 74353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger private boolean mIsSymbols; 751b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka /** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of 7641feaaadb758a8b31d3e436063b4b5faed104d4dsatok * what user actually typed. */ 771b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka private boolean mIsAutoCorrectionActive; 7804448c2978a81b8c479b254e0f40bce128da8f7bTadashi G. Takaoka private boolean mVoiceKeyEnabled; 79507495efd57074994fdc2fda78db9d5345f4a3a8Tadashi G. Takaoka private boolean mVoiceButtonOnPrimary; 809e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka 81717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // TODO: Encapsulate these state handling to separate class and combine with ShiftKeyState 82717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // and ModifierKeyState. 83717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static final int SWITCH_STATE_ALPHA = 0; 84717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static final int SWITCH_STATE_SYMBOL_BEGIN = 1; 85717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static final int SWITCH_STATE_SYMBOL = 2; 869e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // The following states are used only on the distinct multi-touch panel devices. 87717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static final int SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL = 3; 88717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static final int SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE = 4; 89717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static final int SWITCH_STATE_CHORDING_ALPHA = 5; 90717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static final int SWITCH_STATE_CHORDING_SYMBOL = 6; 91717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private int mSwitchState = SWITCH_STATE_ALPHA; 92923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 934199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka // Indicates whether or not we have the settings key in option of settings 944199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka private boolean mSettingsKeyEnabledInSettings; 951508c0e84f0cd93ab6f5d46fea5026e833f299bcKen Wakasa private static final int SETTINGS_KEY_MODE_AUTO = R.string.settings_key_mode_auto; 96503797ae0e55c74068470d237fb47c4da13ec4fbTadashi G. Takaoka private static final int SETTINGS_KEY_MODE_ALWAYS_SHOW = 97503797ae0e55c74068470d237fb47c4da13ec4fbTadashi G. Takaoka R.string.settings_key_mode_always_show; 9817fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa // NOTE: No need to have SETTINGS_KEY_MODE_ALWAYS_HIDE here because it's not being referred to 9917fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa // in the source code now. 10017fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa // Default is SETTINGS_KEY_MODE_AUTO. 10117fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa private static final int DEFAULT_SETTINGS_KEY_MODE = SETTINGS_KEY_MODE_AUTO; 1021508c0e84f0cd93ab6f5d46fea5026e833f299bcKen Wakasa 103f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka private int mThemeIndex; 104e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka private int mKeyboardWidth; 105979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1060ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private static final KeyboardSwitcher sInstance = new KeyboardSwitcher(); 1070ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok 1080ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok public static KeyboardSwitcher getInstance() { 1090ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok return sInstance; 1100ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok } 1110ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok 1120ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private KeyboardSwitcher() { 113e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka // Intentional empty constructor for singleton. 1140ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok } 1150ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok 11627d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa public static void init(LatinIME ims, SharedPreferences prefs) { 1170ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok sInstance.mInputMethodService = ims; 11827d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa sInstance.mPrefs = prefs; 1190ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok sInstance.mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 120979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 12105ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka try { 12205ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka sConfigDefaultKeyboardThemeId = ims.getString( 12305ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka R.string.config_default_keyboard_theme_id); 124f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka sInstance.mThemeIndex = Integer.valueOf( 12505ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka prefs.getString(PREF_KEYBOARD_LAYOUT, sConfigDefaultKeyboardThemeId)); 12605ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka } catch (NumberFormatException e) { 12705ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka sConfigDefaultKeyboardThemeId = "0"; 128f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka sInstance.mThemeIndex = 0; 12905ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka } 1300ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok prefs.registerOnSharedPreferenceChangeListener(sInstance); 131979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 132979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 133cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka public void loadKeyboard(EditorInfo attribute, boolean voiceKeyEnabled, 134507495efd57074994fdc2fda78db9d5345f4a3a8Tadashi G. Takaoka boolean voiceButtonOnPrimary) { 135717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_ALPHA; 136979f8690967ff5409fe18f5085858ccdb8e0ccf1satok try { 137cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka loadKeyboardInternal(attribute, voiceKeyEnabled, voiceButtonOnPrimary, false); 138979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } catch (RuntimeException e) { 1394b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka // Get KeyboardId to record which keyboard has been failed to load. 140cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka final KeyboardId id = getKeyboardId(attribute, false); 1414b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka Log.w(TAG, "loading keyboard failed: " + id, e); 1424b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka LatinImeLogger.logOnException(id.toString(), e); 143979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 144353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger } 145353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger 146cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka private void loadKeyboardInternal(EditorInfo attribute, boolean voiceButtonEnabled, 147507495efd57074994fdc2fda78db9d5345f4a3a8Tadashi G. Takaoka boolean voiceButtonOnPrimary, boolean isSymbols) { 148c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka if (mKeyboardView == null) return; 1498b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 1504b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka mAttribute = attribute; 15104448c2978a81b8c479b254e0f40bce128da8f7bTadashi G. Takaoka mVoiceKeyEnabled = voiceButtonEnabled; 1528b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka mVoiceButtonOnPrimary = voiceButtonOnPrimary; 153c5bb4591b67b165f007e29bd9424d319ac3c7c28Brandon Ballinger mIsSymbols = isSymbols; 1548b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka // Update the settings key state because number of enabled IMEs could have been changed 1554199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka mSettingsKeyEnabledInSettings = getSettingsKeyMode(mPrefs, mInputMethodService); 156cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka final KeyboardId id = getKeyboardId(attribute, isSymbols); 157e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka 158e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka // Note: This comment is only applied for phone number keyboard layout. 159e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka // On non-xlarge device, "@integer/key_switch_alpha_symbol" key code is used to switch 160e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka // between "phone keyboard" and "phone symbols keyboard". But on xlarge device, 161e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka // "@integer/key_shift" key code is used for that purpose in order to properly display 162e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka // "more" and "locked more" key labels. To achieve these behavior, we should initialize 163e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka // mSymbolsId and mSymbolsShiftedId to "phone keyboard" and "phone symbols keyboard" 164e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka // respectively here for xlarge device's layout switching. 165e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka mSymbolsId = makeSiblingKeyboardId(id, R.xml.kbd_symbols, R.xml.kbd_phone); 166e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka mSymbolsShiftedId = makeSiblingKeyboardId( 167e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka id, R.xml.kbd_symbols_shift, R.xml.kbd_phone_symbols); 168e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka 169050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka setKeyboard(getKeyboard(id)); 170050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka } 171050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka 172e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka public void onSizeChanged() { 173e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka final int width = mInputMethodService.getWindow().getWindow().getDecorView().getWidth(); 174e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka if (width == 0) 175e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka return; 176e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka mKeyboardWidth = width; 177e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka // Set keyboard with new width. 178e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka final KeyboardId newId = mCurrentId.cloneWithNewGeometry(width); 179e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka setKeyboard(getKeyboard(newId)); 180e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka } 181e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka 182050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka private void setKeyboard(final Keyboard newKeyboard) { 183c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka final Keyboard oldKeyboard = mKeyboardView.getKeyboard(); 184c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka mKeyboardView.setKeyboard(newKeyboard); 185e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka mCurrentId = newKeyboard.mId; 186e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka final Resources res = mInputMethodService.getResources(); 187c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka mKeyboardView.setKeyPreviewPopupEnabled( 188e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka Settings.Values.isKeyPreviewPopupEnabled(mPrefs, res), 189e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka Settings.Values.getKeyPreviewPopupDismissDelay(mPrefs, res)); 190050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka final boolean localeChanged = (oldKeyboard == null) 191050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka || !newKeyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale); 192050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged); 193353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger } 194353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger 195353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger private LatinKeyboard getKeyboard(KeyboardId id) { 1968b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka final SoftReference<LatinKeyboard> ref = mKeyboardCache.get(id); 197681b676b0aecb30e644f25550018ce2b6cea3e15Tadashi G. Takaoka LatinKeyboard keyboard = (ref == null) ? null : ref.get(); 198681b676b0aecb30e644f25550018ce2b6cea3e15Tadashi G. Takaoka if (keyboard == null) { 199309bff562fbaf47488e6bf6636840f00574187d8Jean Chalard final Resources res = mInputMethodService.getResources(); 200309bff562fbaf47488e6bf6636840f00574187d8Jean Chalard final Locale savedLocale = Utils.setSystemLocale(res, 2010ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mSubtypeSwitcher.getInputLocale()); 2028b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 203e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka keyboard = new LatinKeyboard(mInputMethodService, id, id.mWidth); 204358e485b14938fbcb5af5be75aa29f2b73674100Amith Yamasani 205353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger if (id.mEnableShiftLock) { 206353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger keyboard.enableShiftLock(); 207353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger } 2088b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 2098b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka mKeyboardCache.put(id, new SoftReference<LatinKeyboard>(keyboard)); 210e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka if (DEBUG_CACHE) 2118b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": " 2128b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka + ((ref == null) ? "LOAD" : "GCed") + " id=" + id); 21336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 214309bff562fbaf47488e6bf6636840f00574187d8Jean Chalard Utils.setSystemLocale(res, savedLocale); 215e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka } else if (DEBUG_CACHE) { 2168b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT id=" + id); 217353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger } 2188b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 2191b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka keyboard.onAutoCorrectionStateChanged(mIsAutoCorrectionActive); 2208b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka keyboard.setShifted(false); 221de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka // If the cached keyboard had been switched to another keyboard while the language was 222de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka // displayed on its spacebar, it might have had arbitrary text fade factor. In such case, 2235cd87e1b1c4258e8d016518914eccfbb4437caceTadashi G. Takaoka // we should reset the text fade factor. It is also applicable to shortcut key. 224de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka keyboard.setSpacebarTextFadeFactor(0.0f, null); 2254503e2ea9853c1573f60903d8639d82e39e07c56Tadashi G. Takaoka keyboard.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady(), null); 22675136cd009ef37b9a5a013200444e149f8461ff5Tadashi G. Takaoka keyboard.setSpacebarSlidingLanguageSwitchDiff(0); 227681b676b0aecb30e644f25550018ce2b6cea3e15Tadashi G. Takaoka return keyboard; 228353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger } 229353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger 2304199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka private boolean hasVoiceKey(boolean isSymbols) { 2314199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka return mVoiceKeyEnabled && (isSymbols != mVoiceButtonOnPrimary); 2324199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka } 2334199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka 2344199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka private boolean hasSettingsKey(EditorInfo attribute) { 2354199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka return mSettingsKeyEnabledInSettings 2364199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka && !Utils.inPrivateImeOptions(mInputMethodService.getPackageName(), 2374199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka LatinIME.IME_OPTION_NO_SETTINGS_KEY, attribute); 2384199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka } 2394199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka 240cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka private KeyboardId getKeyboardId(EditorInfo attribute, boolean isSymbols) { 241cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka final int mode = Utils.getKeyboardMode(attribute); 2428b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka final boolean hasVoiceKey = hasVoiceKey(isSymbols); 24359c9930ca98f68aeb6b0b9dc19e29666b8fb152aTadashi G. Takaoka final int charColorId = getColorScheme(); 24459c9930ca98f68aeb6b0b9dc19e29666b8fb152aTadashi G. Takaoka final int xmlId; 245e354a85ef44e13999aaefd735cef7f659090f6e8Ken Wakasa final boolean enableShiftLock; 246e354a85ef44e13999aaefd735cef7f659090f6e8Ken Wakasa 247e354a85ef44e13999aaefd735cef7f659090f6e8Ken Wakasa if (isSymbols) { 2485a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka if (mode == KeyboardId.MODE_PHONE) { 2492c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka xmlId = R.xml.kbd_phone_symbols; 2505a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } else if (mode == KeyboardId.MODE_NUMBER) { 2512c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka // Note: MODE_NUMBER keyboard layout has no "switch alpha symbol" key. 2522c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka xmlId = R.xml.kbd_number; 2532c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka } else { 2542c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka xmlId = R.xml.kbd_symbols; 2552c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka } 256e354a85ef44e13999aaefd735cef7f659090f6e8Ken Wakasa enableShiftLock = false; 2572c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka } else { 2585a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka if (mode == KeyboardId.MODE_PHONE) { 2592c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka xmlId = R.xml.kbd_phone; 2602c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka enableShiftLock = false; 2615a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } else if (mode == KeyboardId.MODE_NUMBER) { 2622c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka xmlId = R.xml.kbd_number; 2632c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka enableShiftLock = false; 2642c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka } else { 2652c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka xmlId = R.xml.kbd_qwerty; 2662c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka enableShiftLock = true; 2672c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka } 268923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2694199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka final boolean hasSettingsKey = hasSettingsKey(attribute); 2709b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka final Resources res = mInputMethodService.getResources(); 2719b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka final int orientation = res.getConfiguration().orientation; 272e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka if (mKeyboardWidth == 0) 273e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka mKeyboardWidth = res.getDisplayMetrics().widthPixels; 2740ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok final Locale locale = mSubtypeSwitcher.getInputLocale(); 2759b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka return new KeyboardId( 276e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka res.getResourceEntryName(xmlId), xmlId, charColorId, locale, orientation, 277e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka mKeyboardWidth, mode, attribute, hasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, 278e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka enableShiftLock); 2794199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka } 2804199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka 281e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka private KeyboardId makeSiblingKeyboardId(KeyboardId base, int alphabet, int phone) { 282e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka final int xmlId = base.mMode == KeyboardId.MODE_PHONE ? phone : alphabet; 283e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka final String xmlName = mInputMethodService.getResources().getResourceEntryName(xmlId); 284e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka return base.cloneWithNewLayout(xmlName, xmlId); 285923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 286923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2873a2896c80475094f751ef447fc9c97028bfc2265Tadashi G. Takaoka public int getKeyboardMode() { 288cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka return mCurrentId != null ? mCurrentId.mMode : KeyboardId.MODE_TEXT; 289923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2901679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka 2913a2896c80475094f751ef447fc9c97028bfc2265Tadashi G. Takaoka public boolean isAlphabetMode() { 292571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka return mCurrentId != null && mCurrentId.isAlphabetKeyboard(); 293923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 294923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2951679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka public boolean isInputViewShown() { 296c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return mKeyboardView != null && mKeyboardView.isShown(); 2971679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka } 2981679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka 2991679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka public boolean isKeyboardAvailable() { 300c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka if (mKeyboardView != null) 301c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return mKeyboardView.getKeyboard() != null; 302b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 303b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 304b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka 305050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka public LatinKeyboard getLatinKeyboard() { 306c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka if (mKeyboardView != null) { 307c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka final Keyboard keyboard = mKeyboardView.getKeyboard(); 308050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka if (keyboard instanceof LatinKeyboard) 309050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka return (LatinKeyboard)keyboard; 310050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka } 311b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return null; 3121679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka } 3131679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka 314f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka public boolean isShiftedOrShiftLocked() { 315b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 316b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (latinKeyboard != null) 317f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka return latinKeyboard.isShiftedOrShiftLocked(); 318b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 3191679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka } 3201679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka 3211679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka public boolean isShiftLocked() { 322b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 323b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (latinKeyboard != null) 324b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return latinKeyboard.isShiftLocked(); 325b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 3261679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka } 3271679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka 328f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka public boolean isAutomaticTemporaryUpperCase() { 329f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 330f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (latinKeyboard != null) 331f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka return latinKeyboard.isAutomaticTemporaryUpperCase(); 332f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka return false; 333f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } 334f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka 335f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka public boolean isManualTemporaryUpperCase() { 336f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 337f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (latinKeyboard != null) 338f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka return latinKeyboard.isManualTemporaryUpperCase(); 339f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka return false; 340f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } 341f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka 342d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka private boolean isManualTemporaryUpperCaseFromAuto() { 343d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 344d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka if (latinKeyboard != null) 345d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka return latinKeyboard.isManualTemporaryUpperCaseFromAuto(); 346d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka return false; 347d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka } 348d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka 349f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka private void setManualTemporaryUpperCase(boolean shifted) { 350b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 3510d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka if (latinKeyboard != null) { 3520d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka // On non-distinct multi touch panel device, we should also turn off the shift locked 3530d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka // state when shift key is pressed to go to normal mode. 3540d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka // On the other hand, on distinct multi touch panel device, turning off the shift locked 3550d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka // state with shift key pressing is handled by onReleaseShift(). 356101a00e3d4b1c29ef2ecdecd1b72b43efde7791aTadashi G. Takaoka if (!hasDistinctMultitouch() && !shifted && latinKeyboard.isShiftLocked()) { 3570d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka latinKeyboard.setShiftLocked(false); 3580d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka } 3590d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka if (latinKeyboard.setShifted(shifted)) { 360c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka mKeyboardView.invalidateAllKeys(); 3610d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka } 362979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 363979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 364979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 365b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka private void setShiftLocked(boolean shiftLocked) { 366b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 367b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (latinKeyboard != null && latinKeyboard.setShiftLocked(shiftLocked)) { 368c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka mKeyboardView.invalidateAllKeys(); 369b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 370979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 371979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 3720d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka /** 3730d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka * Toggle keyboard shift state triggered by user touch event. 3740d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka */ 375b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public void toggleShift() { 376b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mInputMethodService.mHandler.cancelUpdateShiftState(); 377f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 378f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "toggleShift:" 379f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 380f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " shiftKeyState=" + mShiftKeyState); 381b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (isAlphabetMode()) { 382f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka setManualTemporaryUpperCase(!isShiftedOrShiftLocked()); 383b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } else { 384b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka toggleShiftInSymbol(); 385b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 386b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 387b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka 388b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public void toggleCapsLock() { 389b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mInputMethodService.mHandler.cancelUpdateShiftState(); 390f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 391f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "toggleCapsLock:" 392f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 393f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " shiftKeyState=" + mShiftKeyState); 394b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (isAlphabetMode()) { 395b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (isShiftLocked()) { 396f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // Shift key is long pressed while caps lock state, we will toggle back to normal 397f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // state. And mark as if shift key is released. 398f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka setShiftLocked(false); 399f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka mShiftKeyState.onRelease(); 400b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } else { 401b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka setShiftLocked(true); 402b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 403b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 404889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka } 405889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka 406f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka private void setAutomaticTemporaryUpperCase() { 407f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 408f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (latinKeyboard != null) { 409f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka latinKeyboard.setAutomaticTemporaryUpperCase(); 410c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka mKeyboardView.invalidateAllKeys(); 411f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } 412f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } 413f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka 4140d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka /** 4150d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka * Update keyboard shift state triggered by connected EditText status change. 4160d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka */ 417b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public void updateShiftState() { 41845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final ShiftKeyState shiftKeyState = mShiftKeyState; 419f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 420f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "updateShiftState:" 421f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " autoCaps=" + mInputMethodService.getCurrentAutoCapsState() 422f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 42345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka + " shiftKeyState=" + shiftKeyState); 42445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (isAlphabetMode()) { 42545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (!isShiftLocked() && !shiftKeyState.isIgnoring()) { 42645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (shiftKeyState.isReleasing() && mInputMethodService.getCurrentAutoCapsState()) { 42745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka // Only when shift key is releasing, automatic temporary upper case will be set. 42845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka setAutomaticTemporaryUpperCase(); 42945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } else { 43045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka setManualTemporaryUpperCase(shiftKeyState.isMomentary()); 43145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 432f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } 43345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } else { 43445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka // In symbol keyboard mode, we should clear shift key state because only alphabet 43545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka // keyboard has shift key. 43645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka shiftKeyState.onRelease(); 437b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 438889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka } 439889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka 440b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public void changeKeyboardMode() { 441f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 442f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "changeKeyboardMode:" 443f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 444f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " shiftKeyState=" + mShiftKeyState); 445b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka toggleKeyboardMode(); 446b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (isShiftLocked() && isAlphabetMode()) 447b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka setShiftLocked(true); 448b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka updateShiftState(); 449889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka } 450889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka 451e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka public void onPressShift(boolean withSliding) { 452b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (!isKeyboardAvailable()) 453b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return; 454f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka ShiftKeyState shiftKeyState = mShiftKeyState; 455f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 456f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "onPressShift:" 457f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 458e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka + " shiftKeyState=" + shiftKeyState + " sliding=" + withSliding); 459f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (isAlphabetMode()) { 460f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (isShiftLocked()) { 461f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // Shift key is pressed while caps lock state, we will treat this state as shifted 462f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // caps lock state and mark as if shift key pressed while normal state. 463f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka shiftKeyState.onPress(); 4646769c67987f323008647f5d029c02f8cc95272eeTadashi G. Takaoka setManualTemporaryUpperCase(true); 465f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } else if (isAutomaticTemporaryUpperCase()) { 466f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // Shift key is pressed while automatic temporary upper case, we have to move to 467f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // manual temporary upper case. 4686769c67987f323008647f5d029c02f8cc95272eeTadashi G. Takaoka shiftKeyState.onPress(); 469f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka setManualTemporaryUpperCase(true); 470f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } else if (isShiftedOrShiftLocked()) { 471f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // In manual upper case state, we just record shift key has been pressing while 472f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // shifted state. 473f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka shiftKeyState.onPressOnShifted(); 474f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } else { 475f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // In base layout, chording or manual temporary upper case mode is started. 476f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka shiftKeyState.onPress(); 4776769c67987f323008647f5d029c02f8cc95272eeTadashi G. Takaoka toggleShift(); 478f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } 479b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } else { 480f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // In symbol mode, just toggle symbol and symbol more keyboard. 481f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka shiftKeyState.onPress(); 4826769c67987f323008647f5d029c02f8cc95272eeTadashi G. Takaoka toggleShift(); 483717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE; 484b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 485b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 486b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka 487e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka public void onReleaseShift(boolean withSliding) { 488b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (!isKeyboardAvailable()) 489b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return; 490f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka ShiftKeyState shiftKeyState = mShiftKeyState; 491f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 492f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "onReleaseShift:" 493f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 494e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka + " shiftKeyState=" + shiftKeyState + " sliding=" + withSliding); 495b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (isAlphabetMode()) { 496f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (shiftKeyState.isMomentary()) { 497f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // After chording input while normal state. 498f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka toggleShift(); 499e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka } else if (isShiftLocked() && !shiftKeyState.isIgnoring() && !withSliding) { 500f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // Shift has been pressed without chording while caps lock state. 501f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka toggleCapsLock(); 502e541f03286189eebbc4a75615070e0e6f43ec37cTadashi G. Takaoka // To be able to turn off caps lock by "double tap" on shift key, we should ignore 503e541f03286189eebbc4a75615070e0e6f43ec37cTadashi G. Takaoka // the second tap of the "double tap" from now for a while because we just have 504e541f03286189eebbc4a75615070e0e6f43ec37cTadashi G. Takaoka // already turned off caps lock above. 505c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka mKeyboardView.startIgnoringDoubleTap(); 506e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka } else if (isShiftedOrShiftLocked() && shiftKeyState.isPressingOnShifted() 507e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka && !withSliding) { 508f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // Shift has been pressed without chording while shifted state. 509b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka toggleShift(); 510e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka } else if (isManualTemporaryUpperCaseFromAuto() && shiftKeyState.isPressing() 511e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka && !withSliding) { 512d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka // Shift has been pressed without chording while manual temporary upper case 513d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka // transited from automatic temporary upper case. 514d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka toggleShift(); 515b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 516717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } else { 517717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // In symbol mode, snap back to the previous keyboard mode if the user chords the shift 518717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // key and another key, then releases the shift key. 519717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (mSwitchState == SWITCH_STATE_CHORDING_SYMBOL) { 520717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka toggleShift(); 521717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } 522b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 523f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka shiftKeyState.onRelease(); 524889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka } 525889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka 5266c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka public void onPressSymbol() { 527f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 5289e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka Log.d(TAG, "onPressSymbol:" 529f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 530f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " symbolKeyState=" + mSymbolKeyState); 531b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka changeKeyboardMode(); 5326c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka mSymbolKeyState.onPress(); 533717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL; 5346c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka } 5356c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka 5366c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka public void onReleaseSymbol() { 537f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 5389e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka Log.d(TAG, "onReleaseSymbol:" 539f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 540f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " symbolKeyState=" + mSymbolKeyState); 5419e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Snap back to the previous keyboard mode if the user chords the mode change key and 542717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // another key, then releases the mode change key. 543717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (mSwitchState == SWITCH_STATE_CHORDING_ALPHA) { 544b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka changeKeyboardMode(); 545717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } 5466c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka mSymbolKeyState.onRelease(); 5476c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka } 5486c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka 5496c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka public void onOtherKeyPressed() { 55045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (DEBUG_STATE) 55145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka Log.d(TAG, "onOtherKeyPressed:" 55245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 55345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka + " shiftKeyState=" + mShiftKeyState 55445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka + " symbolKeyState=" + mSymbolKeyState); 555f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka mShiftKeyState.onOtherKeyPressed(); 5566c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka mSymbolKeyState.onOtherKeyPressed(); 5576c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka } 5586c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka 5595f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka public void onCancelInput() { 5605f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // Snap back to the previous keyboard mode if the user cancels sliding input. 561717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (getPointerCount() == 1) { 562717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) { 563717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka changeKeyboardMode(); 564717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } else if (mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE) { 565717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka toggleShift(); 566717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } 567717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } 5685f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka } 5695f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka 570b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka private void toggleShiftInSymbol() { 5717e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka if (isAlphabetMode()) 5727e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka return; 5738b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka final LatinKeyboard keyboard; 5747e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka if (mCurrentId.equals(mSymbolsId) || !mCurrentId.equals(mSymbolsShiftedId)) { 575e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka keyboard = getKeyboard(mSymbolsShiftedId); 57612659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaoka // Symbol shifted keyboard has an ALT key that has a caps lock style indicator. To 577e7c0e73a19e6eb6cb9a4aded8a0a7240db544d85Tadashi G. Takaoka // enable the indicator, we need to call setShiftLocked(true). 5788b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka keyboard.setShiftLocked(true); 5797e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka } else { 580e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka keyboard = getKeyboard(mSymbolsId); 58112659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaoka // Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the 582e7c0e73a19e6eb6cb9a4aded8a0a7240db544d85Tadashi G. Takaoka // indicator, we need to call setShiftLocked(false). 583e7c0e73a19e6eb6cb9a4aded8a0a7240db544d85Tadashi G. Takaoka keyboard.setShiftLocked(false); 584923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 585050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka setKeyboard(keyboard); 586923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 587923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 588717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka public boolean isInMomentarySwitchState() { 589717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka return mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL 590717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka || mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE; 5919e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } 5929e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka 593cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka public boolean isVibrateAndSoundFeedbackRequired() { 594c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return mKeyboardView == null || !mKeyboardView.isInSlidingKeyInput(); 595cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka } 596cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka 5979e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka private int getPointerCount() { 598c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return mKeyboardView == null ? 0 : mKeyboardView.getPointerCount(); 5999e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } 6009e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka 601f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka private void toggleKeyboardMode() { 602cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka loadKeyboardInternal(mAttribute, mVoiceKeyEnabled, mVoiceButtonOnPrimary, !mIsSymbols); 603e354a85ef44e13999aaefd735cef7f659090f6e8Ken Wakasa if (mIsSymbols) { 604717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; 605b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } else { 606717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_ALPHA; 607b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 608b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 609b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 610c8b9afe0378e3f33c3f83271bd1df9678a70c2a2Tadashi G. Takaoka public boolean hasDistinctMultitouch() { 611c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return mKeyboardView != null && mKeyboardView.hasDistinctMultitouch(); 612c8b9afe0378e3f33c3f83271bd1df9678a70c2a2Tadashi G. Takaoka } 613c8b9afe0378e3f33c3f83271bd1df9678a70c2a2Tadashi G. Takaoka 614717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static boolean isSpaceCharacter(int c) { 615717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka return c == Keyboard.CODE_SPACE || c == Keyboard.CODE_ENTER; 616717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } 617717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka 618717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static boolean isQuoteCharacter(int c) { 619717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // Apostrophe, quotation mark. 6200730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard if (c == Keyboard.CODE_SINGLE_QUOTE || c == Keyboard.CODE_DOUBLE_QUOTE) 621717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka return true; 622717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u2018: Left single quotation mark 623717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u2019: Right single quotation mark 624717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u201a: Single low-9 quotation mark 625717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u201b: Single high-reversed-9 quotation mark 626717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u201c: Left double quotation mark 627717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u201d: Right double quotation mark 628717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u201e: Double low-9 quotation mark 629717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u201f: Double high-reversed-9 quotation mark 630717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (c >= '\u2018' && c <= '\u201f') 631717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka return true; 632717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u00ab: Left-pointing double angle quotation mark 633717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u00bb: Right-pointing double angle quotation mark 634717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (c == '\u00ab' || c == '\u00bb') 635717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka return true; 636717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka return false; 637717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } 638717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka 639b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani /** 6409e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka * Updates state machine to figure out when to automatically snap back to the previous mode. 641b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani */ 642717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka public void onKey(int code) { 6439e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka if (DEBUG_STATE) 644717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka Log.d(TAG, "onKey: code=" + code + " switchState=" + mSwitchState 6459e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka + " pointers=" + getPointerCount()); 646717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka switch (mSwitchState) { 647717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: 6489e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Only distinct multi touch devices can be in this state. 6495f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // On non-distinct multi touch devices, mode change key is handled by 6505f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // {@link LatinIME#onCodeInput}, not by {@link LatinIME#onPress} and 651717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // {@link LatinIME#onRelease}. So, on such devices, {@link #mSwitchState} starts 652717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // from {@link #SWITCH_STATE_SYMBOL_BEGIN}, or {@link #SWITCH_STATE_ALPHA}, not from 653717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // {@link #SWITCH_STATE_MOMENTARY}. 654717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { 6559e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Detected only the mode change key has been pressed, and then released. 6569e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka if (mIsSymbols) { 657717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; 6589e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } else { 659717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_ALPHA; 6609e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } 6619e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } else if (getPointerCount() == 1) { 6629e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Snap back to the previous keyboard mode if the user pressed the mode change key 6639e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // and slid to other key, then released the finger. 6645f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // If the user cancels the sliding input, snapping back to the previous keyboard 6655f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // mode is handled by {@link #onCancelInput}. 6669e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka changeKeyboardMode(); 6679e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } else { 6689e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Chording input is being started. The keyboard mode will be snapped back to the 6699e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // previous mode in {@link onReleaseSymbol} when the mode change key is released. 670717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_CHORDING_ALPHA; 671717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } 672717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka break; 673717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE: 674717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (code == Keyboard.CODE_SHIFT) { 675717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // Detected only the shift key has been pressed on symbol layout, and then released. 676717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; 677717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } else if (getPointerCount() == 1) { 678717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // Snap back to the previous keyboard mode if the user pressed the shift key on 679717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // symbol mode and slid to other key, then released the finger. 680717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka toggleShift(); 681717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_SYMBOL; 682717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } else { 683717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // Chording input is being started. The keyboard mode will be snapped back to the 684717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // previous mode in {@link onReleaseShift} when the shift key is released. 685717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_CHORDING_SYMBOL; 6869e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } 6879e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka break; 688717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka case SWITCH_STATE_SYMBOL_BEGIN: 689717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (!isSpaceCharacter(code) && code >= 0) { 690717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_SYMBOL; 691b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 6920b4757604de15bfe66c10e9cdf01da6d437c6082Ken Wakasa // Snap back to alpha keyboard mode immediately if user types a quote character. 6930b4757604de15bfe66c10e9cdf01da6d437c6082Ken Wakasa if (isQuoteCharacter(code)) { 6940b4757604de15bfe66c10e9cdf01da6d437c6082Ken Wakasa changeKeyboardMode(); 6950b4757604de15bfe66c10e9cdf01da6d437c6082Ken Wakasa } 696b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka break; 697717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka case SWITCH_STATE_SYMBOL: 698717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka case SWITCH_STATE_CHORDING_SYMBOL: 6999e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Snap back to alpha keyboard mode if user types one or more non-space/enter 7000b4757604de15bfe66c10e9cdf01da6d437c6082Ken Wakasa // characters followed by a space/enter or a quote character. 701717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (isSpaceCharacter(code) || isQuoteCharacter(code)) { 702b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka changeKeyboardMode(); 703b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 704b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka break; 705b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 706923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 707979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 708c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka public LatinKeyboardView getKeyboardView() { 709c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return mKeyboardView; 710979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 711979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 712c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka public View onCreateInputView() { 713f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka return createInputView(mThemeIndex, true); 714979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 715979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 716f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka // Instance variable only for {@link #createInputView(int, boolean)}. 717f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka private View mCurrentInputView; 718979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 719f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka private View createInputView(final int newThemeIndex, final boolean forceRecreate) { 720f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka if (mCurrentInputView != null && mThemeIndex == newThemeIndex && !forceRecreate) 721f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka return mCurrentInputView; 722f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka 723f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka if (mKeyboardView != null) { 724f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka mKeyboardView.closing(); 725f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka } 726f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka final int themeIndex = (newThemeIndex < KEYBOARD_THEMES.length) ? newThemeIndex 727f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka : Integer.valueOf(sConfigDefaultKeyboardThemeId); 728f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka 729f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka Utils.GCUtils.getInstance().reset(); 730f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka boolean tryGC = true; 731f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { 732f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka try { 733f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka mCurrentInputView = LayoutInflater.from(mInputMethodService).inflate( 734f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka KEYBOARD_THEMES[themeIndex], null); 735f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka tryGC = false; 736f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka } catch (OutOfMemoryError e) { 737f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka Log.w(TAG, "load keyboard failed: " + e); 738f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka tryGC = Utils.GCUtils.getInstance().tryGCOrWait(mThemeIndex + "," + themeIndex, e); 739f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka } catch (InflateException e) { 740f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka Log.w(TAG, "load keyboard failed: " + e); 741f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka tryGC = Utils.GCUtils.getInstance().tryGCOrWait(mThemeIndex + "," + themeIndex, e); 742979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 743979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 744f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka 745f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka mKeyboardView = (LatinKeyboardView) mCurrentInputView.findViewById( 746f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka R.id.latin_keyboard_view); 747f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka mKeyboardView.setOnKeyboardActionListener(mInputMethodService); 748f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka mThemeIndex = themeIndex; 749f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka return mCurrentInputView; 7508d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka } 7518d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka 752f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka private void postSetInputView(final View newInputView) { 753979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mInputMethodService.mHandler.post(new Runnable() { 7548d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka @Override 755979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public void run() { 756f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka if (newInputView != null) { 757f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka mInputMethodService.setInputView(newInputView); 758979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 759979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mInputMethodService.updateInputViewShown(); 7608d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka } 7618d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka }); 762979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 763979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 7648d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka @Override 765979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { 766979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (PREF_KEYBOARD_LAYOUT.equals(key)) { 7678b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka final int layoutId = Integer.valueOf( 76805ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka sharedPreferences.getString(key, sConfigDefaultKeyboardThemeId)); 769f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka postSetInputView(createInputView(layoutId, false)); 7709502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka } else if (Settings.PREF_SETTINGS_KEY.equals(key)) { 7714199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka mSettingsKeyEnabledInSettings = getSettingsKeyMode(sharedPreferences, 7724199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka mInputMethodService); 773f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka postSetInputView(createInputView(mThemeIndex, true)); 774979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 775979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 776979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 77759c9930ca98f68aeb6b0b9dc19e29666b8fb152aTadashi G. Takaoka private int getColorScheme() { 778c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return (mKeyboardView != null) 779c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka ? mKeyboardView.getColorScheme() : KeyboardView.COLOR_SCHEME_WHITE; 780979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 781979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 7821b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka public void onAutoCorrectionStateChanged(boolean isAutoCorrection) { 7831b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (isAutoCorrection != mIsAutoCorrectionActive) { 784c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka LatinKeyboardView keyboardView = getKeyboardView(); 7851b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mIsAutoCorrectionActive = isAutoCorrection; 78641feaaadb758a8b31d3e436063b4b5faed104d4dsatok keyboardView.invalidateKey(((LatinKeyboard) keyboardView.getKeyboard()) 7871b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka .onAutoCorrectionStateChanged(isAutoCorrection)); 78841feaaadb758a8b31d3e436063b4b5faed104d4dsatok } 78941feaaadb758a8b31d3e436063b4b5faed104d4dsatok } 7901508c0e84f0cd93ab6f5d46fea5026e833f299bcKen Wakasa 7918b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka private static boolean getSettingsKeyMode(SharedPreferences prefs, Context context) { 7928b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka Resources resources = context.getResources(); 793503797ae0e55c74068470d237fb47c4da13ec4fbTadashi G. Takaoka final boolean showSettingsKeyOption = resources.getBoolean( 794503797ae0e55c74068470d237fb47c4da13ec4fbTadashi G. Takaoka R.bool.config_enable_show_settings_key_option); 79517fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa if (showSettingsKeyOption) { 7969502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka final String settingsKeyMode = prefs.getString(Settings.PREF_SETTINGS_KEY, 79717fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa resources.getString(DEFAULT_SETTINGS_KEY_MODE)); 79817fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa // We show the settings key when 1) SETTINGS_KEY_MODE_ALWAYS_SHOW or 79917fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa // 2) SETTINGS_KEY_MODE_AUTO and there are two or more enabled IMEs on the system 80017fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa if (settingsKeyMode.equals(resources.getString(SETTINGS_KEY_MODE_ALWAYS_SHOW)) 80117fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa || (settingsKeyMode.equals(resources.getString(SETTINGS_KEY_MODE_AUTO)) 8029502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka && Utils.hasMultipleEnabledIMEsOrSubtypes( 803610f1dc8553cf2ed97e763a06a19380c4a6cd636satok (InputMethodManagerCompatWrapper.getInstance(context))))) { 8048b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka return true; 80517fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa } 8064199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka return false; 8071508c0e84f0cd93ab6f5d46fea5026e833f299bcKen Wakasa } 8084199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka // If the show settings key option is disabled, we always try showing the settings key. 8094199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka return true; 8101508c0e84f0cd93ab6f5d46fea5026e833f299bcKen Wakasa } 811923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 812