KeyboardSwitcher.java revision 4199e29a7d796191d3e13ef07e6e80e91834fe7a
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 19571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.LatinIME; 20571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.LatinImeLogger; 21571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.R; 225cd87e1b1c4258e8d016518914eccfbb4437caceTadashi G. Takaokaimport com.android.inputmethod.latin.Settings; 23571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.SubtypeSwitcher; 245cd87e1b1c4258e8d016518914eccfbb4437caceTadashi G. Takaokaimport com.android.inputmethod.latin.Utils; 255a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka 268b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaokaimport android.content.Context; 27979f8690967ff5409fe18f5085858ccdb8e0ccf1satokimport android.content.SharedPreferences; 2836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasaniimport android.content.res.Resources; 298b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaokaimport android.util.Log; 30979f8690967ff5409fe18f5085858ccdb8e0ccf1satokimport android.view.InflateException; 314b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaokaimport android.view.inputmethod.EditorInfo; 3279efbed76f638be298493107fa2d0cd1b5eb529esatokimport android.view.inputmethod.InputMethodManager; 3336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 34681b676b0aecb30e644f25550018ce2b6cea3e15Tadashi G. Takaokaimport java.lang.ref.SoftReference; 3512659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaokaimport java.util.HashMap; 3612659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaokaimport java.util.Locale; 3712659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaoka 38979f8690967ff5409fe18f5085858ccdb8e0ccf1satokpublic class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener { 398b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka private static final String TAG = "KeyboardSwitcher"; 408b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka private static final boolean DEBUG = false; 41f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka public static final boolean DEBUG_STATE = false; 42923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 4305ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka private static String sConfigDefaultKeyboardThemeId; 44a327485e595c9f7676989097c830ff452085d4c9satok public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902"; 4505ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka private static final int[] KEYBOARD_THEMES = { 4675fde6489039c09056fb5e64d39630ece5ad57cfTadashi G. Takaoka R.layout.input_basic, 4775fde6489039c09056fb5e64d39630ece5ad57cfTadashi G. Takaoka R.layout.input_basic_highcontrast, 4875fde6489039c09056fb5e64d39630ece5ad57cfTadashi G. Takaoka R.layout.input_stone_normal, 4975fde6489039c09056fb5e64d39630ece5ad57cfTadashi G. Takaoka R.layout.input_stone_bold, 5075fde6489039c09056fb5e64d39630ece5ad57cfTadashi G. Takaoka R.layout.input_gingerbread, 5105ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka R.layout.input_honeycomb, 5275fde6489039c09056fb5e64d39630ece5ad57cfTadashi G. Takaoka }; 53979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 540ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private SubtypeSwitcher mSubtypeSwitcher; 5527d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa private SharedPreferences mPrefs; 560ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok 573a2896c80475094f751ef447fc9c97028bfc2265Tadashi G. Takaoka private LatinKeyboardView mInputView; 580ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private LatinIME mInputMethodService; 5931adfa78e2edae188edb05e869f9f68798857582satok 60f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift"); 61f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol"); 62889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka 63353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger private KeyboardId mSymbolsId; 64353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger private KeyboardId mSymbolsShiftedId; 65353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger 66353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger private KeyboardId mCurrentId; 678b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache = 688b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka new HashMap<KeyboardId, SoftReference<LatinKeyboard>>(); 69466741d8a78965b8509bf527344f289e50873092Mike LeBeau 704b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka private EditorInfo mAttribute; 71353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger private boolean mIsSymbols; 721b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka /** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of 7341feaaadb758a8b31d3e436063b4b5faed104d4dsatok * what user actually typed. */ 741b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka private boolean mIsAutoCorrectionActive; 7504448c2978a81b8c479b254e0f40bce128da8f7bTadashi G. Takaoka private boolean mVoiceKeyEnabled; 76507495efd57074994fdc2fda78db9d5345f4a3a8Tadashi G. Takaoka private boolean mVoiceButtonOnPrimary; 779e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka 789e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka private static final int AUTO_MODE_SWITCH_STATE_ALPHA = 0; 799e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka private static final int AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN = 1; 809e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka private static final int AUTO_MODE_SWITCH_STATE_SYMBOL = 2; 819e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // The following states are used only on the distinct multi-touch panel devices. 829e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka private static final int AUTO_MODE_SWITCH_STATE_MOMENTARY = 3; 839e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka private static final int AUTO_MODE_SWITCH_STATE_CHORDING = 4; 849e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka private int mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA; 85923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 864199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka // Indicates whether or not we have the settings key in option of settings 874199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka private boolean mSettingsKeyEnabledInSettings; 881508c0e84f0cd93ab6f5d46fea5026e833f299bcKen Wakasa private static final int SETTINGS_KEY_MODE_AUTO = R.string.settings_key_mode_auto; 89503797ae0e55c74068470d237fb47c4da13ec4fbTadashi G. Takaoka private static final int SETTINGS_KEY_MODE_ALWAYS_SHOW = 90503797ae0e55c74068470d237fb47c4da13ec4fbTadashi G. Takaoka R.string.settings_key_mode_always_show; 9117fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa // NOTE: No need to have SETTINGS_KEY_MODE_ALWAYS_HIDE here because it's not being referred to 9217fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa // in the source code now. 9317fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa // Default is SETTINGS_KEY_MODE_AUTO. 9417fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa private static final int DEFAULT_SETTINGS_KEY_MODE = SETTINGS_KEY_MODE_AUTO; 951508c0e84f0cd93ab6f5d46fea5026e833f299bcKen Wakasa 96979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private int mLayoutId; 97979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 980ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private static final KeyboardSwitcher sInstance = new KeyboardSwitcher(); 990ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok 1000ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok public static KeyboardSwitcher getInstance() { 1010ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok return sInstance; 1020ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok } 1030ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok 1040ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private KeyboardSwitcher() { 105e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka // Intentional empty constructor for singleton. 1060ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok } 1070ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok 10827d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa public static void init(LatinIME ims, SharedPreferences prefs) { 1090ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok sInstance.mInputMethodService = ims; 11027d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa sInstance.mPrefs = prefs; 1110ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok sInstance.mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 112979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 11305ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka try { 11405ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka sConfigDefaultKeyboardThemeId = ims.getString( 11505ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka R.string.config_default_keyboard_theme_id); 11605ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka sInstance.mLayoutId = Integer.valueOf( 11705ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka prefs.getString(PREF_KEYBOARD_LAYOUT, sConfigDefaultKeyboardThemeId)); 11805ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka } catch (NumberFormatException e) { 11905ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka sConfigDefaultKeyboardThemeId = "0"; 12005ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka sInstance.mLayoutId = 0; 12105ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka } 1220ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok prefs.registerOnSharedPreferenceChangeListener(sInstance); 123979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 124979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 125cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka public void loadKeyboard(EditorInfo attribute, boolean voiceKeyEnabled, 126507495efd57074994fdc2fda78db9d5345f4a3a8Tadashi G. Takaoka boolean voiceButtonOnPrimary) { 1279e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA; 128979f8690967ff5409fe18f5085858ccdb8e0ccf1satok try { 129cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka loadKeyboardInternal(attribute, voiceKeyEnabled, voiceButtonOnPrimary, false); 130979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } catch (RuntimeException e) { 1314b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka // Get KeyboardId to record which keyboard has been failed to load. 132cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka final KeyboardId id = getKeyboardId(attribute, false); 1334b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka Log.w(TAG, "loading keyboard failed: " + id, e); 1344b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka LatinImeLogger.logOnException(id.toString(), e); 135979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 136353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger } 137353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger 138cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka private void loadKeyboardInternal(EditorInfo attribute, boolean voiceButtonEnabled, 139507495efd57074994fdc2fda78db9d5345f4a3a8Tadashi G. Takaoka boolean voiceButtonOnPrimary, boolean isSymbols) { 1406516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani if (mInputView == null) return; 1418b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 1424b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka mAttribute = attribute; 14304448c2978a81b8c479b254e0f40bce128da8f7bTadashi G. Takaoka mVoiceKeyEnabled = voiceButtonEnabled; 1448b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka mVoiceButtonOnPrimary = voiceButtonOnPrimary; 145c5bb4591b67b165f007e29bd9424d319ac3c7c28Brandon Ballinger mIsSymbols = isSymbols; 1468b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka // Update the settings key state because number of enabled IMEs could have been changed 1474199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka mSettingsKeyEnabledInSettings = getSettingsKeyMode(mPrefs, mInputMethodService); 148cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka final KeyboardId id = getKeyboardId(attribute, isSymbols); 149466741d8a78965b8509bf527344f289e50873092Mike LeBeau 1508bec4aa912c193135bebacfc75dc15f06c5dce6eTadashi G. Takaoka final Keyboard oldKeyboard = mInputView.getKeyboard(); 1518bec4aa912c193135bebacfc75dc15f06c5dce6eTadashi G. Takaoka if (oldKeyboard != null && oldKeyboard.mId.equals(id)) 1528bec4aa912c193135bebacfc75dc15f06c5dce6eTadashi G. Takaoka return; 1538bec4aa912c193135bebacfc75dc15f06c5dce6eTadashi G. Takaoka 1544199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka makeSymbolsKeyboardIds(id.mMode, attribute); 155353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger mCurrentId = id; 1568bec4aa912c193135bebacfc75dc15f06c5dce6eTadashi G. Takaoka mInputView.setPreviewEnabled(mInputMethodService.getPopupOn()); 157050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka setKeyboard(getKeyboard(id)); 158050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka } 159050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka 160050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka private void setKeyboard(final Keyboard newKeyboard) { 161050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka final Keyboard oldKeyboard = mInputView.getKeyboard(); 162050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka mInputView.setKeyboard(newKeyboard); 163050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka final boolean localeChanged = (oldKeyboard == null) 164050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka || !newKeyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale); 165050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged); 166353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger } 167353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger 168353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger private LatinKeyboard getKeyboard(KeyboardId id) { 1698b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka final SoftReference<LatinKeyboard> ref = mKeyboardCache.get(id); 170681b676b0aecb30e644f25550018ce2b6cea3e15Tadashi G. Takaoka LatinKeyboard keyboard = (ref == null) ? null : ref.get(); 171681b676b0aecb30e644f25550018ce2b6cea3e15Tadashi G. Takaoka if (keyboard == null) { 1720ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok final Locale savedLocale = mSubtypeSwitcher.changeSystemLocale( 1730ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mSubtypeSwitcher.getInputLocale()); 1748b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 175b0465116bd3786174ccd0034c8a165ebc723b60fTadashi G. Takaoka keyboard = new LatinKeyboard(mInputMethodService, id); 176358e485b14938fbcb5af5be75aa29f2b73674100Amith Yamasani 177353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger if (id.mEnableShiftLock) { 178353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger keyboard.enableShiftLock(); 179353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger } 1808b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 1818b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka mKeyboardCache.put(id, new SoftReference<LatinKeyboard>(keyboard)); 1828b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka if (DEBUG) 1838b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": " 1848b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka + ((ref == null) ? "LOAD" : "GCed") + " id=" + id); 18536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani 1860ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok mSubtypeSwitcher.changeSystemLocale(savedLocale); 1878b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka } else if (DEBUG) { 1888b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT id=" + id); 189353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger } 1908b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 1911b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka keyboard.onAutoCorrectionStateChanged(mIsAutoCorrectionActive); 1928b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka keyboard.setShifted(false); 193de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka // If the cached keyboard had been switched to another keyboard while the language was 194de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka // displayed on its spacebar, it might have had arbitrary text fade factor. In such case, 1955cd87e1b1c4258e8d016518914eccfbb4437caceTadashi G. Takaoka // we should reset the text fade factor. It is also applicable to shortcut key. 196de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka keyboard.setSpacebarTextFadeFactor(0.0f, null); 1975cd87e1b1c4258e8d016518914eccfbb4437caceTadashi G. Takaoka keyboard.updateShortcutKey(mSubtypeSwitcher.isShortcutAvailable(), null); 198681b676b0aecb30e644f25550018ce2b6cea3e15Tadashi G. Takaoka return keyboard; 199353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger } 200353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger 2014199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka private boolean hasVoiceKey(boolean isSymbols) { 2024199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka return mVoiceKeyEnabled && (isSymbols != mVoiceButtonOnPrimary); 2034199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka } 2044199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka 2054199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka private boolean hasSettingsKey(EditorInfo attribute) { 2064199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka return mSettingsKeyEnabledInSettings 2074199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka && !Utils.inPrivateImeOptions(mInputMethodService.getPackageName(), 2084199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka LatinIME.IME_OPTION_NO_SETTINGS_KEY, attribute); 2094199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka } 2104199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka 211cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka private KeyboardId getKeyboardId(EditorInfo attribute, boolean isSymbols) { 212cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka final int mode = Utils.getKeyboardMode(attribute); 2138b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka final boolean hasVoiceKey = hasVoiceKey(isSymbols); 21459c9930ca98f68aeb6b0b9dc19e29666b8fb152aTadashi G. Takaoka final int charColorId = getColorScheme(); 21559c9930ca98f68aeb6b0b9dc19e29666b8fb152aTadashi G. Takaoka final int xmlId; 216e354a85ef44e13999aaefd735cef7f659090f6e8Ken Wakasa final boolean enableShiftLock; 217e354a85ef44e13999aaefd735cef7f659090f6e8Ken Wakasa 218e354a85ef44e13999aaefd735cef7f659090f6e8Ken Wakasa if (isSymbols) { 2195a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka if (mode == KeyboardId.MODE_PHONE) { 2202c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka xmlId = R.xml.kbd_phone_symbols; 2215a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } else if (mode == KeyboardId.MODE_NUMBER) { 2222c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka // Note: MODE_NUMBER keyboard layout has no "switch alpha symbol" key. 2232c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka xmlId = R.xml.kbd_number; 2242c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka } else { 2252c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka xmlId = R.xml.kbd_symbols; 2262c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka } 227e354a85ef44e13999aaefd735cef7f659090f6e8Ken Wakasa enableShiftLock = false; 2282c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka } else { 2295a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka if (mode == KeyboardId.MODE_PHONE) { 2302c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka xmlId = R.xml.kbd_phone; 2312c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka enableShiftLock = false; 2325a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } else if (mode == KeyboardId.MODE_NUMBER) { 2332c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka xmlId = R.xml.kbd_number; 2342c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka enableShiftLock = false; 2352c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka } else { 2362c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka xmlId = R.xml.kbd_qwerty; 2372c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka enableShiftLock = true; 2382c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka } 239923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2404199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka final boolean hasSettingsKey = hasSettingsKey(attribute); 2419b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka final Resources res = mInputMethodService.getResources(); 2429b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka final int orientation = res.getConfiguration().orientation; 2430ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok final Locale locale = mSubtypeSwitcher.getInputLocale(); 2449b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka return new KeyboardId( 2454b13b4f94215368c6387b2564bdaf2cbcbe4c130Tadashi G. Takaoka res.getResourceEntryName(xmlId), xmlId, charColorId, locale, orientation, mode, 2464199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka attribute, hasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, enableShiftLock); 2474199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka } 2484199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka 2494199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka private void makeSymbolsKeyboardIds(final int mode, EditorInfo attribute) { 2504199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka final Locale locale = mSubtypeSwitcher.getInputLocale(); 2514199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka final Resources res = mInputMethodService.getResources(); 2524199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka final int orientation = res.getConfiguration().orientation; 2534199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka final int colorScheme = getColorScheme(); 2544199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka final boolean hasVoiceKey = mVoiceKeyEnabled && !mVoiceButtonOnPrimary; 2554199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka final boolean hasSettingsKey = hasSettingsKey(attribute); 2564199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka // Note: This comment is only applied for phone number keyboard layout. 2574199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka // On non-xlarge device, "@integer/key_switch_alpha_symbol" key code is used to switch 2584199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka // between "phone keyboard" and "phone symbols keyboard". But on xlarge device, 2594199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka // "@integer/key_shift" key code is used for that purpose in order to properly display 2604199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka // "more" and "locked more" key labels. To achieve these behavior, we should initialize 2614199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka // mSymbolsId and mSymbolsShiftedId to "phone keyboard" and "phone symbols keyboard" 2624199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka // respectively here for xlarge device's layout switching. 2634199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka int xmlId = mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone : R.xml.kbd_symbols; 2644199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka final String xmlName = res.getResourceEntryName(xmlId); 2654199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka mSymbolsId = new KeyboardId(xmlName, xmlId, colorScheme, locale, orientation, mode, 2664199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka attribute, hasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, true); 2674199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka xmlId = mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone_symbols : R.xml.kbd_symbols_shift; 2684199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka mSymbolsShiftedId = new KeyboardId(xmlName, xmlId, colorScheme, locale, orientation, mode, 2694199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka attribute, hasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, true); 270923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 271923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2723a2896c80475094f751ef447fc9c97028bfc2265Tadashi G. Takaoka public int getKeyboardMode() { 273cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka return mCurrentId != null ? mCurrentId.mMode : KeyboardId.MODE_TEXT; 274923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2751679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka 2763a2896c80475094f751ef447fc9c97028bfc2265Tadashi G. Takaoka public boolean isAlphabetMode() { 277571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka return mCurrentId != null && mCurrentId.isAlphabetKeyboard(); 278923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 279923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 2801679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka public boolean isInputViewShown() { 2811679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka return mInputView != null && mInputView.isShown(); 2821679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka } 2831679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka 2841679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka public boolean isKeyboardAvailable() { 285b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (mInputView != null) 286050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka return mInputView.getKeyboard() != null; 287b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 288b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 289b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka 290050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka public LatinKeyboard getLatinKeyboard() { 291050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka if (mInputView != null) { 292050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka final Keyboard keyboard = mInputView.getKeyboard(); 293050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka if (keyboard instanceof LatinKeyboard) 294050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka return (LatinKeyboard)keyboard; 295050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka } 296b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return null; 2971679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka } 2981679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka 2991679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka public void keyReleased() { 300b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 301b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (latinKeyboard != null) 3021679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka latinKeyboard.keyReleased(); 3031679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka } 3041679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka 305f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka public boolean isShiftedOrShiftLocked() { 306b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 307b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (latinKeyboard != null) 308f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka return latinKeyboard.isShiftedOrShiftLocked(); 309b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 3101679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka } 3111679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka 3121679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka public boolean isShiftLocked() { 313b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 314b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (latinKeyboard != null) 315b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return latinKeyboard.isShiftLocked(); 316b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 3171679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka } 3181679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka 319f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka public boolean isAutomaticTemporaryUpperCase() { 320f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 321f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (latinKeyboard != null) 322f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka return latinKeyboard.isAutomaticTemporaryUpperCase(); 323f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka return false; 324f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } 325f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka 326f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka public boolean isManualTemporaryUpperCase() { 327f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 328f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (latinKeyboard != null) 329f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka return latinKeyboard.isManualTemporaryUpperCase(); 330f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka return false; 331f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } 332f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka 333d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka private boolean isManualTemporaryUpperCaseFromAuto() { 334d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 335d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka if (latinKeyboard != null) 336d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka return latinKeyboard.isManualTemporaryUpperCaseFromAuto(); 337d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka return false; 338d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka } 339d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka 340f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka private void setManualTemporaryUpperCase(boolean shifted) { 341b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 3420d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka if (latinKeyboard != null) { 3430d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka // On non-distinct multi touch panel device, we should also turn off the shift locked 3440d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka // state when shift key is pressed to go to normal mode. 3450d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka // On the other hand, on distinct multi touch panel device, turning off the shift locked 3460d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka // state with shift key pressing is handled by onReleaseShift(). 3470d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka if (!hasDistinctMultitouch() && !shifted && latinKeyboard.isShiftLocked()) { 3480d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka latinKeyboard.setShiftLocked(false); 3490d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka } 3500d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka if (latinKeyboard.setShifted(shifted)) { 3510d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka mInputView.invalidateAllKeys(); 3520d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka } 353979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 354979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 355979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 356b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka private void setShiftLocked(boolean shiftLocked) { 357b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 358b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (latinKeyboard != null && latinKeyboard.setShiftLocked(shiftLocked)) { 359b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mInputView.invalidateAllKeys(); 360b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 361979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 362979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 3630d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka /** 3640d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka * Toggle keyboard shift state triggered by user touch event. 3650d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka */ 366b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public void toggleShift() { 367b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mInputMethodService.mHandler.cancelUpdateShiftState(); 368f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 369f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "toggleShift:" 370f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 371f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " shiftKeyState=" + mShiftKeyState); 372b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (isAlphabetMode()) { 373f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka setManualTemporaryUpperCase(!isShiftedOrShiftLocked()); 374b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } else { 375b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka toggleShiftInSymbol(); 376b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 377b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 378b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka 379b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public void toggleCapsLock() { 380b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mInputMethodService.mHandler.cancelUpdateShiftState(); 381f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 382f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "toggleCapsLock:" 383f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 384f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " shiftKeyState=" + mShiftKeyState); 385b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (isAlphabetMode()) { 386b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (isShiftLocked()) { 387f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // Shift key is long pressed while caps lock state, we will toggle back to normal 388f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // state. And mark as if shift key is released. 389f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka setShiftLocked(false); 390f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka mShiftKeyState.onRelease(); 391b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } else { 392b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka setShiftLocked(true); 393b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 394b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 395889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka } 396889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka 397f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka private void setAutomaticTemporaryUpperCase() { 398f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 399f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (latinKeyboard != null) { 400f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka latinKeyboard.setAutomaticTemporaryUpperCase(); 401f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka mInputView.invalidateAllKeys(); 402f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } 403f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } 404f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka 4050d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka /** 4060d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka * Update keyboard shift state triggered by connected EditText status change. 4070d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka */ 408b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public void updateShiftState() { 40945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final ShiftKeyState shiftKeyState = mShiftKeyState; 410f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 411f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "updateShiftState:" 412f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " autoCaps=" + mInputMethodService.getCurrentAutoCapsState() 413f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 41445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka + " shiftKeyState=" + shiftKeyState); 41545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (isAlphabetMode()) { 41645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (!isShiftLocked() && !shiftKeyState.isIgnoring()) { 41745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (shiftKeyState.isReleasing() && mInputMethodService.getCurrentAutoCapsState()) { 41845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka // Only when shift key is releasing, automatic temporary upper case will be set. 41945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka setAutomaticTemporaryUpperCase(); 42045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } else { 42145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka setManualTemporaryUpperCase(shiftKeyState.isMomentary()); 42245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 423f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } 42445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } else { 42545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka // In symbol keyboard mode, we should clear shift key state because only alphabet 42645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka // keyboard has shift key. 42745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka shiftKeyState.onRelease(); 428b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 429889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka } 430889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka 431b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public void changeKeyboardMode() { 432f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 433f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "changeKeyboardMode:" 434f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 435f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " shiftKeyState=" + mShiftKeyState); 436b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka toggleKeyboardMode(); 437b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (isShiftLocked() && isAlphabetMode()) 438b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka setShiftLocked(true); 439b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka updateShiftState(); 440889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka } 441889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka 442b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public void onPressShift() { 443b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (!isKeyboardAvailable()) 444b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return; 445f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka ShiftKeyState shiftKeyState = mShiftKeyState; 446f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 447f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "onPressShift:" 448f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 449f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " shiftKeyState=" + shiftKeyState); 450f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (isAlphabetMode()) { 451f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (isShiftLocked()) { 452f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // Shift key is pressed while caps lock state, we will treat this state as shifted 453f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // caps lock state and mark as if shift key pressed while normal state. 454f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka shiftKeyState.onPress(); 4556769c67987f323008647f5d029c02f8cc95272eeTadashi G. Takaoka setManualTemporaryUpperCase(true); 456f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } else if (isAutomaticTemporaryUpperCase()) { 457f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // Shift key is pressed while automatic temporary upper case, we have to move to 458f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // manual temporary upper case. 4596769c67987f323008647f5d029c02f8cc95272eeTadashi G. Takaoka shiftKeyState.onPress(); 460f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka setManualTemporaryUpperCase(true); 461f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } else if (isShiftedOrShiftLocked()) { 462f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // In manual upper case state, we just record shift key has been pressing while 463f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // shifted state. 464f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka shiftKeyState.onPressOnShifted(); 465f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } else { 466f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // In base layout, chording or manual temporary upper case mode is started. 467f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka shiftKeyState.onPress(); 4686769c67987f323008647f5d029c02f8cc95272eeTadashi G. Takaoka toggleShift(); 469f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } 470b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } else { 471f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // In symbol mode, just toggle symbol and symbol more keyboard. 472f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka shiftKeyState.onPress(); 4736769c67987f323008647f5d029c02f8cc95272eeTadashi G. Takaoka toggleShift(); 474b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 475b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 476b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka 477b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public void onReleaseShift() { 478b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (!isKeyboardAvailable()) 479b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return; 480f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka ShiftKeyState shiftKeyState = mShiftKeyState; 481f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 482f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "onReleaseShift:" 483f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 484f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " shiftKeyState=" + shiftKeyState); 485b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (isAlphabetMode()) { 486f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (shiftKeyState.isMomentary()) { 487f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // After chording input while normal state. 488f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka toggleShift(); 489f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } else if (isShiftLocked() && !shiftKeyState.isIgnoring()) { 490f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // Shift has been pressed without chording while caps lock state. 491f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka toggleCapsLock(); 492f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } else if (isShiftedOrShiftLocked() && shiftKeyState.isPressingOnShifted()) { 493f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // Shift has been pressed without chording while shifted state. 494b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka toggleShift(); 495d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka } else if (isManualTemporaryUpperCaseFromAuto() && shiftKeyState.isPressing()) { 496d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka // Shift has been pressed without chording while manual temporary upper case 497d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka // transited from automatic temporary upper case. 498d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka toggleShift(); 499b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 500b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 501f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka shiftKeyState.onRelease(); 502889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka } 503889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka 5046c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka public void onPressSymbol() { 505f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 5069e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka Log.d(TAG, "onPressSymbol:" 507f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 508f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " symbolKeyState=" + mSymbolKeyState); 509b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka changeKeyboardMode(); 5106c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka mSymbolKeyState.onPress(); 5119e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_MOMENTARY; 5126c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka } 5136c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka 5146c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka public void onReleaseSymbol() { 515f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 5169e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka Log.d(TAG, "onReleaseSymbol:" 517f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 518f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " symbolKeyState=" + mSymbolKeyState); 5199e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Snap back to the previous keyboard mode if the user chords the mode change key and 5209e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // other key, then released the mode change key. 5219e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka if (mAutoModeSwitchState == AUTO_MODE_SWITCH_STATE_CHORDING) 522b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka changeKeyboardMode(); 5236c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka mSymbolKeyState.onRelease(); 5246c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka } 5256c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka 5266c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka public void onOtherKeyPressed() { 52745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (DEBUG_STATE) 52845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka Log.d(TAG, "onOtherKeyPressed:" 52945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 53045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka + " shiftKeyState=" + mShiftKeyState 53145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka + " symbolKeyState=" + mSymbolKeyState); 532f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka mShiftKeyState.onOtherKeyPressed(); 5336c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka mSymbolKeyState.onOtherKeyPressed(); 5346c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka } 5356c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka 5365f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka public void onCancelInput() { 5375f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // Snap back to the previous keyboard mode if the user cancels sliding input. 5385f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka if (mAutoModeSwitchState == AUTO_MODE_SWITCH_STATE_MOMENTARY && getPointerCount() == 1) 5395f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka changeKeyboardMode(); 5405f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka } 5415f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka 542b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka private void toggleShiftInSymbol() { 5437e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka if (isAlphabetMode()) 5447e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka return; 5458b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka final LatinKeyboard keyboard; 5467e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka if (mCurrentId.equals(mSymbolsId) || !mCurrentId.equals(mSymbolsShiftedId)) { 547353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger mCurrentId = mSymbolsShiftedId; 5488b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka keyboard = getKeyboard(mCurrentId); 54912659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaoka // Symbol shifted keyboard has an ALT key that has a caps lock style indicator. To 55012659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaoka // enable the indicator, we need to call enableShiftLock() and setShiftLocked(true). 55112659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaoka // Thus we can keep the ALT key's Key.on value true while LatinKey.onRelease() is 55212659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaoka // called. 5538b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka keyboard.setShiftLocked(true); 5547e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka } else { 555353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger mCurrentId = mSymbolsId; 5568b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka keyboard = getKeyboard(mCurrentId); 55712659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaoka // Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the 55812659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaoka // indicator, we need to call enableShiftLock() and setShiftLocked(false). 5598b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka keyboard.setShifted(false); 560923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 561050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka setKeyboard(keyboard); 562923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 563923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 5649e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka public boolean isInMomentaryAutoModeSwitchState() { 5659e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka return mAutoModeSwitchState == AUTO_MODE_SWITCH_STATE_MOMENTARY; 5669e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } 5679e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka 568cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka public boolean isVibrateAndSoundFeedbackRequired() { 569cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka return mInputView == null || !mInputView.isInSlidingKeyInput(); 570cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka } 571cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka 5729e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka private int getPointerCount() { 5739e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka return mInputView == null ? 0 : mInputView.getPointerCount(); 5749e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } 5759e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka 576f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka private void toggleKeyboardMode() { 577cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka loadKeyboardInternal(mAttribute, mVoiceKeyEnabled, mVoiceButtonOnPrimary, !mIsSymbols); 578e354a85ef44e13999aaefd735cef7f659090f6e8Ken Wakasa if (mIsSymbols) { 5799e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN; 580b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } else { 5819e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA; 582b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 583b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 584b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 585c8b9afe0378e3f33c3f83271bd1df9678a70c2a2Tadashi G. Takaoka public boolean hasDistinctMultitouch() { 586c8b9afe0378e3f33c3f83271bd1df9678a70c2a2Tadashi G. Takaoka return mInputView != null && mInputView.hasDistinctMultitouch(); 587c8b9afe0378e3f33c3f83271bd1df9678a70c2a2Tadashi G. Takaoka } 588c8b9afe0378e3f33c3f83271bd1df9678a70c2a2Tadashi G. Takaoka 589b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani /** 5909e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka * Updates state machine to figure out when to automatically snap back to the previous mode. 591b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani */ 592b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public void onKey(int key) { 5939e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka if (DEBUG_STATE) 5949e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka Log.d(TAG, "onKey: code=" + key + " autoModeSwitchState=" + mAutoModeSwitchState 5959e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka + " pointers=" + getPointerCount()); 5969e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka switch (mAutoModeSwitchState) { 5979e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka case AUTO_MODE_SWITCH_STATE_MOMENTARY: 5989e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Only distinct multi touch devices can be in this state. 5995f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // On non-distinct multi touch devices, mode change key is handled by 6005f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // {@link LatinIME#onCodeInput}, not by {@link LatinIME#onPress} and 6015f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // {@link LatinIME#onRelease}. So, on such devices, {@link #mAutoModeSwitchState} starts 6025f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // from {@link #AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN}, or 6035f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // {@link #AUTO_MODE_SWITCH_STATE_ALPHA}, not from 6045f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // {@link #AUTO_MODE_SWITCH_STATE_MOMENTARY}. 6059e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka if (key == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { 6069e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Detected only the mode change key has been pressed, and then released. 6079e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka if (mIsSymbols) { 6089e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN; 6099e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } else { 6109e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA; 6119e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } 6129e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } else if (getPointerCount() == 1) { 6139e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Snap back to the previous keyboard mode if the user pressed the mode change key 6149e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // and slid to other key, then released the finger. 6155f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // If the user cancels the sliding input, snapping back to the previous keyboard 6165f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // mode is handled by {@link #onCancelInput}. 6179e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka changeKeyboardMode(); 6189e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } else { 6199e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Chording input is being started. The keyboard mode will be snapped back to the 6209e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // previous mode in {@link onReleaseSymbol} when the mode change key is released. 6219e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_CHORDING; 6229e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } 6239e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka break; 6249e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka case AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN: 6255ef421b58afa7bc58be40ed9331ce04998efbf56Tadashi G. Takaoka if (key != Keyboard.CODE_SPACE && key != Keyboard.CODE_ENTER && key >= 0) { 6269e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_SYMBOL; 627b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 628b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka break; 6299e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka case AUTO_MODE_SWITCH_STATE_SYMBOL: 6309e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Snap back to alpha keyboard mode if user types one or more non-space/enter 6319e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // characters followed by a space/enter. 632571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka if (key == Keyboard.CODE_ENTER || key == Keyboard.CODE_SPACE) { 633b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka changeKeyboardMode(); 634b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 635b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka break; 636b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 637923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 638979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 639979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public LatinKeyboardView getInputView() { 640979f8690967ff5409fe18f5085858ccdb8e0ccf1satok return mInputView; 641979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 642979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 6438d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka public LatinKeyboardView onCreateInputView() { 6448d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka createInputViewInternal(mLayoutId, true); 6458d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka return mInputView; 646979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 647979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 6488d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka private void createInputViewInternal(int newLayout, boolean forceReset) { 649e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka int layoutId = newLayout; 650e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka if (mLayoutId != layoutId || mInputView == null || forceReset) { 651979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mInputView != null) { 652979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mInputView.closing(); 653979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 65405ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka if (KEYBOARD_THEMES.length <= layoutId) { 65505ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka layoutId = Integer.valueOf(sConfigDefaultKeyboardThemeId); 656979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 657979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 6589502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka Utils.GCUtils.getInstance().reset(); 659979f8690967ff5409fe18f5085858ccdb8e0ccf1satok boolean tryGC = true; 6609502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { 661979f8690967ff5409fe18f5085858ccdb8e0ccf1satok try { 662979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mInputView = (LatinKeyboardView) mInputMethodService.getLayoutInflater( 66305ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka ).inflate(KEYBOARD_THEMES[layoutId], null); 664979f8690967ff5409fe18f5085858ccdb8e0ccf1satok tryGC = false; 665979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } catch (OutOfMemoryError e) { 6667f0befe1f0e346ec6468f229f337eda32e19f6d8Tadashi G. Takaoka Log.w(TAG, "load keyboard failed: " + e); 6679502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka tryGC = Utils.GCUtils.getInstance().tryGCOrWait( 668e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mLayoutId + "," + layoutId, e); 669979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } catch (InflateException e) { 6707f0befe1f0e346ec6468f229f337eda32e19f6d8Tadashi G. Takaoka Log.w(TAG, "load keyboard failed: " + e); 6719502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka tryGC = Utils.GCUtils.getInstance().tryGCOrWait( 672e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mLayoutId + "," + layoutId, e); 673979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 674979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 675979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mInputView.setOnKeyboardActionListener(mInputMethodService); 676e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka mLayoutId = layoutId; 677979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 6788d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka } 6798d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka 6808d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka private void postSetInputView() { 681979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mInputMethodService.mHandler.post(new Runnable() { 6828d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka @Override 683979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public void run() { 684979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (mInputView != null) { 685979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mInputMethodService.setInputView(mInputView); 686979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 687979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mInputMethodService.updateInputViewShown(); 6888d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka } 6898d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka }); 690979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 691979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 6928d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka @Override 693979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { 694979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (PREF_KEYBOARD_LAYOUT.equals(key)) { 6958b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka final int layoutId = Integer.valueOf( 69605ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka sharedPreferences.getString(key, sConfigDefaultKeyboardThemeId)); 6978d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka createInputViewInternal(layoutId, false); 6988d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka postSetInputView(); 6999502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka } else if (Settings.PREF_SETTINGS_KEY.equals(key)) { 7004199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka mSettingsKeyEnabledInSettings = getSettingsKeyMode(sharedPreferences, 7014199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka mInputMethodService); 7028d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka createInputViewInternal(mLayoutId, true); 7038d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka postSetInputView(); 704979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 705979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 706979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 70759c9930ca98f68aeb6b0b9dc19e29666b8fb152aTadashi G. Takaoka private int getColorScheme() { 70859c9930ca98f68aeb6b0b9dc19e29666b8fb152aTadashi G. Takaoka return (mInputView != null) 7095a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka ? mInputView.getColorScheme() : KeyboardView.COLOR_SCHEME_WHITE; 710979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 711979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 7121b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka public void onAutoCorrectionStateChanged(boolean isAutoCorrection) { 7131b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka if (isAutoCorrection != mIsAutoCorrectionActive) { 71441feaaadb758a8b31d3e436063b4b5faed104d4dsatok LatinKeyboardView keyboardView = getInputView(); 7151b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mIsAutoCorrectionActive = isAutoCorrection; 71641feaaadb758a8b31d3e436063b4b5faed104d4dsatok keyboardView.invalidateKey(((LatinKeyboard) keyboardView.getKeyboard()) 7171b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka .onAutoCorrectionStateChanged(isAutoCorrection)); 71841feaaadb758a8b31d3e436063b4b5faed104d4dsatok } 71941feaaadb758a8b31d3e436063b4b5faed104d4dsatok } 7201508c0e84f0cd93ab6f5d46fea5026e833f299bcKen Wakasa 7218b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka private static boolean getSettingsKeyMode(SharedPreferences prefs, Context context) { 7228b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka Resources resources = context.getResources(); 723503797ae0e55c74068470d237fb47c4da13ec4fbTadashi G. Takaoka final boolean showSettingsKeyOption = resources.getBoolean( 724503797ae0e55c74068470d237fb47c4da13ec4fbTadashi G. Takaoka R.bool.config_enable_show_settings_key_option); 72517fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa if (showSettingsKeyOption) { 7269502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka final String settingsKeyMode = prefs.getString(Settings.PREF_SETTINGS_KEY, 72717fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa resources.getString(DEFAULT_SETTINGS_KEY_MODE)); 72817fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa // We show the settings key when 1) SETTINGS_KEY_MODE_ALWAYS_SHOW or 72917fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa // 2) SETTINGS_KEY_MODE_AUTO and there are two or more enabled IMEs on the system 73017fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa if (settingsKeyMode.equals(resources.getString(SETTINGS_KEY_MODE_ALWAYS_SHOW)) 73117fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa || (settingsKeyMode.equals(resources.getString(SETTINGS_KEY_MODE_AUTO)) 7329502cc177cc53678c9ddcc01d4d046f69220e13bTadashi G. Takaoka && Utils.hasMultipleEnabledIMEsOrSubtypes( 73379efbed76f638be298493107fa2d0cd1b5eb529esatok ((InputMethodManager) context.getSystemService( 73479efbed76f638be298493107fa2d0cd1b5eb529esatok Context.INPUT_METHOD_SERVICE))))) { 7358b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka return true; 73617fcd719de9a0ddcf9fd712481b28038419eec4eKen Wakasa } 7374199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka return false; 7381508c0e84f0cd93ab6f5d46fea5026e833f299bcKen Wakasa } 7394199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka // If the show settings key option is disabled, we always try showing the settings key. 7404199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka return true; 7411508c0e84f0cd93ab6f5d46fea5026e833f299bcKen Wakasa } 742923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 743