KeyboardSwitcher.java revision af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6
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; 21364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaokaimport android.content.res.Configuration; 22c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.content.res.Resources; 23b39f612d9791877bf0136fa7af9ae054092b9eabTadashi G. Takaokaimport android.util.DisplayMetrics; 24c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.util.Log; 2513a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaokaimport android.view.ContextThemeWrapper; 26c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.view.InflateException; 27c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.view.LayoutInflater; 28c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.view.View; 29c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.view.inputmethod.EditorInfo; 30c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka 315ac4638f999db4fea8a9e24171dbceb640a10858Alan Viveretteimport com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; 3272934bd5967d0127f71fd4d66158b18b4e6ceefeTadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.ModifierKeyState; 3372934bd5967d0127f71fd4d66158b18b4e6ceefeTadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.ShiftKeyState; 34571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.LatinIME; 35571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.LatinImeLogger; 36571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.R; 375cd87e1b1c4258e8d016518914eccfbb4437caceTadashi G. Takaokaimport com.android.inputmethod.latin.Settings; 38571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.SubtypeSwitcher; 395cd87e1b1c4258e8d016518914eccfbb4437caceTadashi G. Takaokaimport com.android.inputmethod.latin.Utils; 405a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka 41681b676b0aecb30e644f25550018ce2b6cea3e15Tadashi G. Takaokaimport java.lang.ref.SoftReference; 4212659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaokaimport java.util.HashMap; 4312659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaokaimport java.util.Locale; 4412659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaoka 45979f8690967ff5409fe18f5085858ccdb8e0ccf1satokpublic class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener { 46c25e07d21261583d0eeca5aa0fb6e3ffe93dc603Tadashi G. Takaoka private static final String TAG = KeyboardSwitcher.class.getSimpleName(); 47c25e07d21261583d0eeca5aa0fb6e3ffe93dc603Tadashi G. Takaoka private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG; 48f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka public static final boolean DEBUG_STATE = false; 49923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 50a327485e595c9f7676989097c830ff452085d4c9satok public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902"; 5105ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka private static final int[] KEYBOARD_THEMES = { 5213a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka R.style.KeyboardTheme, 5313a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka R.style.KeyboardTheme_HighContrast, 5413a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka R.style.KeyboardTheme_Stone, 5513a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka R.style.KeyboardTheme_Stone_Bold, 5613a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka R.style.KeyboardTheme_Gingerbread, 579116bf18f9c83084f9d451e2e709eff32db27d36Tadashi G. Takaoka R.style.KeyboardTheme_IceCreamSandwich, 5875fde6489039c09056fb5e64d39630ece5ad57cfTadashi G. Takaoka }; 59979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 600ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private SubtypeSwitcher mSubtypeSwitcher; 6127d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa private SharedPreferences mPrefs; 620ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok 6386e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka private View mCurrentInputView; 64c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka private LatinKeyboardView mKeyboardView; 650ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private LatinIME mInputMethodService; 660a054dd1075d679385434ecef38a3d88c7551d7aTadashi G. Takaoka private String mPackageName; 670a054dd1075d679385434ecef38a3d88c7551d7aTadashi G. Takaoka private Resources mResources; 6831adfa78e2edae188edb05e869f9f68798857582satok 69717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // TODO: Combine these key state objects with auto mode switch state. 70f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift"); 71f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol"); 72889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka 7360ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka private KeyboardId mMainKeyboardId; 7460ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka private KeyboardId mSymbolsKeyboardId; 7560ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka private KeyboardId mSymbolsShiftedKeyboardId; 76353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger 77353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger private KeyboardId mCurrentId; 788b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache = 798b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka new HashMap<KeyboardId, SoftReference<LatinKeyboard>>(); 80466741d8a78965b8509bf527344f289e50873092Mike LeBeau 81055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka private KeyboardLayoutState mSavedKeyboardState = new KeyboardLayoutState(); 82055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 831b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka /** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of 8441feaaadb758a8b31d3e436063b4b5faed104d4dsatok * what user actually typed. */ 851b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka private boolean mIsAutoCorrectionActive; 869e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka 87717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // TODO: Encapsulate these state handling to separate class and combine with ShiftKeyState 88717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // and ModifierKeyState. 89717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static final int SWITCH_STATE_ALPHA = 0; 90717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static final int SWITCH_STATE_SYMBOL_BEGIN = 1; 91717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static final int SWITCH_STATE_SYMBOL = 2; 929e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // The following states are used only on the distinct multi-touch panel devices. 93717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static final int SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL = 3; 94717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static final int SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE = 4; 95717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static final int SWITCH_STATE_CHORDING_ALPHA = 5; 96717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static final int SWITCH_STATE_CHORDING_SYMBOL = 6; 97717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private int mSwitchState = SWITCH_STATE_ALPHA; 98923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 995a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka private int mThemeIndex = -1; 1005a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka private Context mThemeContext; 101979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1020ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private static final KeyboardSwitcher sInstance = new KeyboardSwitcher(); 1030ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok 104055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka public class KeyboardLayoutState { 105055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka private boolean mIsValid; 106055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka private boolean mIsAlphabetMode; 107055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka private boolean mIsShiftLocked; 108055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka private boolean mIsShifted; 109055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 110055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka public boolean isValid() { 111055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka return mIsValid; 112055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 113055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 114055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka public void save() { 11594ac3d760b98aa148cc9386e0a4b4a20978db85dTadashi G. Takaoka if (mCurrentId == null) { 11694ac3d760b98aa148cc9386e0a4b4a20978db85dTadashi G. Takaoka return; 11794ac3d760b98aa148cc9386e0a4b4a20978db85dTadashi G. Takaoka } 118055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka mIsAlphabetMode = isAlphabetMode(); 11938b5605feed7260a6dc43ce7bd88d0f95cf43261Tadashi G. Takaoka if (mIsAlphabetMode) { 12038b5605feed7260a6dc43ce7bd88d0f95cf43261Tadashi G. Takaoka mIsShiftLocked = isShiftLocked(); 12138b5605feed7260a6dc43ce7bd88d0f95cf43261Tadashi G. Takaoka mIsShifted = !mIsShiftLocked && isShiftedOrShiftLocked(); 12238b5605feed7260a6dc43ce7bd88d0f95cf43261Tadashi G. Takaoka } else { 12338b5605feed7260a6dc43ce7bd88d0f95cf43261Tadashi G. Takaoka mIsShiftLocked = false; 12494ac3d760b98aa148cc9386e0a4b4a20978db85dTadashi G. Takaoka mIsShifted = mCurrentId.equals(mSymbolsShiftedKeyboardId); 12538b5605feed7260a6dc43ce7bd88d0f95cf43261Tadashi G. Takaoka } 126055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka mIsValid = true; 127055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 128055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 129055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka public KeyboardId getKeyboardId() { 130055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka if (!mIsValid) return mMainKeyboardId; 131055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 132055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka if (mIsAlphabetMode) { 133055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka return mMainKeyboardId; 134055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } else { 135055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka return mIsShifted ? mSymbolsShiftedKeyboardId : mSymbolsKeyboardId; 136055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 137055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 138055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 139055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka public void restore() { 140055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka if (!mIsValid) return; 141055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka mIsValid = false; 142055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 143055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka if (mIsAlphabetMode) { 144055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka final boolean isAlphabetMode = isAlphabetMode(); 145055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka final boolean isShiftLocked = isAlphabetMode && isShiftLocked(); 146055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka final boolean isShifted = !isShiftLocked && isShiftedOrShiftLocked(); 147055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka if (mIsShiftLocked != isShiftLocked) { 148055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka toggleCapsLock(); 149055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } else if (mIsShifted != isShifted) { 150055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka onPressShift(false); 151055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka onReleaseShift(false); 152055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 153055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 154055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 155055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 156055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 1570ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok public static KeyboardSwitcher getInstance() { 1580ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok return sInstance; 1590ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok } 1600ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok 1610ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok private KeyboardSwitcher() { 162e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka // Intentional empty constructor for singleton. 1630ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok } 1640ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok 16527d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa public static void init(LatinIME ims, SharedPreferences prefs) { 166364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka sInstance.initInternal(ims, prefs); 167364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka } 168364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka 169364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka private void initInternal(LatinIME ims, SharedPreferences prefs) { 170364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka mInputMethodService = ims; 171364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka mPackageName = ims.getPackageName(); 172364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka mResources = ims.getResources(); 173364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka mPrefs = prefs; 174364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka mSubtypeSwitcher = SubtypeSwitcher.getInstance(); 175364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka setContextThemeWrapper(ims, getKeyboardThemeIndex(ims, prefs)); 176364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka prefs.registerOnSharedPreferenceChangeListener(this); 1775a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka } 178979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 1795a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka private static int getKeyboardThemeIndex(Context context, SharedPreferences prefs) { 1805a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka final String defaultThemeId = context.getString(R.string.config_default_keyboard_theme_id); 1815a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka final String themeId = prefs.getString(PREF_KEYBOARD_LAYOUT, defaultThemeId); 18205ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka try { 1835a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka final int themeIndex = Integer.valueOf(themeId); 1845a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka if (themeIndex >= 0 && themeIndex < KEYBOARD_THEMES.length) 1855a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka return themeIndex; 18605ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka } catch (NumberFormatException e) { 1875a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka // Format error, keyboard theme is default to 0. 1885a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka } 1895a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka Log.w(TAG, "Illegal keyboard theme in preference: " + themeId + ", default to 0"); 1905a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka return 0; 1915a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka } 1925a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka 1935a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka private void setContextThemeWrapper(Context context, int themeIndex) { 1945a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka if (mThemeIndex != themeIndex) { 1955a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka mThemeIndex = themeIndex; 1965a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka mThemeContext = new ContextThemeWrapper(context, KEYBOARD_THEMES[themeIndex]); 1975a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka mKeyboardCache.clear(); 19805ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka } 199979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 200979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 2012ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa public void loadKeyboard(EditorInfo editorInfo, Settings.Values settingsValues) { 202979f8690967ff5409fe18f5085858ccdb8e0ccf1satok try { 2032ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa mMainKeyboardId = getKeyboardId(editorInfo, false, false, settingsValues); 2042ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa mSymbolsKeyboardId = getKeyboardId(editorInfo, true, false, settingsValues); 2052ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa mSymbolsShiftedKeyboardId = getKeyboardId(editorInfo, true, true, settingsValues); 206055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka setKeyboard(getKeyboard(mSavedKeyboardState.getKeyboardId())); 207979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } catch (RuntimeException e) { 20860ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka Log.w(TAG, "loading keyboard failed: " + mMainKeyboardId, e); 20960ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka LatinImeLogger.logOnException(mMainKeyboardId.toString(), e); 210979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 211353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger } 212353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger 213055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka public KeyboardLayoutState getKeyboardState() { 214055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka return mSavedKeyboardState; 215055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 216055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 217055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka public void onFinishInputView() { 218055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka mIsAutoCorrectionActive = false; 219055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 220055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 221c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka public void onHideWindow() { 222c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka mIsAutoCorrectionActive = false; 223c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka } 224c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka 225055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka private void setKeyboard(final Keyboard keyboard) { 226c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka final Keyboard oldKeyboard = mKeyboardView.getKeyboard(); 227055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka mKeyboardView.setKeyboard(keyboard); 228055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka mCurrentId = keyboard.mId; 229055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka mSwitchState = getSwitchState(mCurrentId); 230055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka updateShiftLockState(keyboard); 231c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka mKeyboardView.setKeyPreviewPopupEnabled( 2320a054dd1075d679385434ecef38a3d88c7551d7aTadashi G. Takaoka Settings.Values.isKeyPreviewPopupEnabled(mPrefs, mResources), 2330a054dd1075d679385434ecef38a3d88c7551d7aTadashi G. Takaoka Settings.Values.getKeyPreviewPopupDismissDelay(mPrefs, mResources)); 234050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka final boolean localeChanged = (oldKeyboard == null) 235055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka || !keyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale); 236050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged); 237286a5bf1c68c8dd06ece9701a904593af2457586Ken Wakasa updateShiftState(); 238353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger } 239353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger 240055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka private int getSwitchState(KeyboardId id) { 241055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka return id.equals(mMainKeyboardId) ? SWITCH_STATE_ALPHA : SWITCH_STATE_SYMBOL_BEGIN; 242055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 243055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 244055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka private void updateShiftLockState(Keyboard keyboard) { 245055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka if (mCurrentId.equals(mSymbolsShiftedKeyboardId)) { 246055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka // Symbol keyboard may have an ALT key that has a caps lock style indicator (a.k.a. 247055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka // sticky shift key). To show or dismiss the indicator, we need to call setShiftLocked() 248055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka // that takes care of the current keyboard having such ALT key or not. 249055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka keyboard.setShiftLocked(keyboard.hasShiftLockKey()); 250055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } else if (mCurrentId.equals(mSymbolsKeyboardId)) { 251055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka // Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the 252055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka // indicator, we need to call setShiftLocked(false). 253055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka keyboard.setShiftLocked(false); 254055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 255055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka } 256055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka 257353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger private LatinKeyboard getKeyboard(KeyboardId id) { 2588b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka final SoftReference<LatinKeyboard> ref = mKeyboardCache.get(id); 259681b676b0aecb30e644f25550018ce2b6cea3e15Tadashi G. Takaoka LatinKeyboard keyboard = (ref == null) ? null : ref.get(); 260681b676b0aecb30e644f25550018ce2b6cea3e15Tadashi G. Takaoka if (keyboard == null) { 261af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka final Locale savedLocale = Utils.setSystemLocale(mResources, id.mLocale); 2628da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka try { 2638da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka keyboard = new LatinKeyboard.Builder(mThemeContext).load(id).build(); 2648da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka } finally { 2658da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka Utils.setSystemLocale(mResources, savedLocale); 2668da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka } 2678b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka mKeyboardCache.put(id, new SoftReference<LatinKeyboard>(keyboard)); 2688da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka 2698da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka if (DEBUG_CACHE) { 2708b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": " 2718b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka + ((ref == null) ? "LOAD" : "GCed") + " id=" + id); 2728da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka } 273e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka } else if (DEBUG_CACHE) { 2748b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT id=" + id); 275353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger } 2768b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka 2771b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka keyboard.onAutoCorrectionStateChanged(mIsAutoCorrectionActive); 27873c02390d31bbf32b78763db66b04004666fb5a3Tadashi G. Takaoka keyboard.setShiftLocked(false); 2798b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka keyboard.setShifted(false); 280de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka // If the cached keyboard had been switched to another keyboard while the language was 281de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka // displayed on its spacebar, it might have had arbitrary text fade factor. In such case, 2825cd87e1b1c4258e8d016518914eccfbb4437caceTadashi G. Takaoka // we should reset the text fade factor. It is also applicable to shortcut key. 283de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka keyboard.setSpacebarTextFadeFactor(0.0f, null); 2844503e2ea9853c1573f60903d8639d82e39e07c56Tadashi G. Takaoka keyboard.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady(), null); 285681b676b0aecb30e644f25550018ce2b6cea3e15Tadashi G. Takaoka return keyboard; 286353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger } 287353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger 2882ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa private KeyboardId getKeyboardId(EditorInfo editorInfo, final boolean isSymbols, 2892ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa final boolean isShift, Settings.Values settingsValues) { 2902ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa final int mode = Utils.getKeyboardMode(editorInfo); 29159c9930ca98f68aeb6b0b9dc19e29666b8fb152aTadashi G. Takaoka final int xmlId; 29260ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka switch (mode) { 29360ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka case KeyboardId.MODE_PHONE: 29460ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka xmlId = (isSymbols && isShift) ? R.xml.kbd_phone_shift : R.xml.kbd_phone; 29560ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka break; 29660ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka case KeyboardId.MODE_NUMBER: 29760ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka xmlId = R.xml.kbd_number; 29860ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka break; 29960ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka default: 30060ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka if (isSymbols) { 30160ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka xmlId = isShift ? R.xml.kbd_symbols_shift : R.xml.kbd_symbols; 3022c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka } else { 3032c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka xmlId = R.xml.kbd_qwerty; 3042c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka } 30560ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka break; 306923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 30760ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka 308cee174b8ccb47ccddc8a8a7e88a9c617f9b5e766Ken Wakasa final boolean settingsKeyEnabled = settingsValues.isSettingsKeyEnabled(); 30973e716f20284f929b2c0323c9e4759efe558de9dTadashi G. Takaoka final boolean noMicrophone = Utils.inPrivateImeOptions( 31073e716f20284f929b2c0323c9e4759efe558de9dTadashi G. Takaoka mPackageName, LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo) 31173e716f20284f929b2c0323c9e4759efe558de9dTadashi G. Takaoka || Utils.inPrivateImeOptions( 31273e716f20284f929b2c0323c9e4759efe558de9dTadashi G. Takaoka null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo); 31373e716f20284f929b2c0323c9e4759efe558de9dTadashi G. Takaoka final boolean voiceKeyEnabled = settingsValues.isVoiceKeyEnabled(editorInfo) 31473e716f20284f929b2c0323c9e4759efe558de9dTadashi G. Takaoka && !noMicrophone; 3152ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa final boolean voiceKeyOnMain = settingsValues.isVoiceKeyOnMain(); 3160a054dd1075d679385434ecef38a3d88c7551d7aTadashi G. Takaoka final boolean noSettingsKey = Utils.inPrivateImeOptions( 3172ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa mPackageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, editorInfo); 3182ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa final boolean hasSettingsKey = settingsKeyEnabled && !noSettingsKey; 3192ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa final int f2KeyMode = getF2KeyMode(settingsKeyEnabled, noSettingsKey); 320c3afe2c244c14ed0f8a355fe608b3402e3656330Tadashi G. Takaoka final boolean hasShortcutKey = voiceKeyEnabled && (isSymbols != voiceKeyOnMain); 321af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka final boolean forceAscii = Utils.inPrivateImeOptions( 322af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, editorInfo); 323af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka final boolean asciiCapable = mSubtypeSwitcher.currentSubtypeContainsExtraValueKey( 324af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE); 325af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka final Locale locale = (forceAscii && !asciiCapable) 326af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka ? Locale.US : mSubtypeSwitcher.getInputLocale(); 3272ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa final Configuration conf = mResources.getConfiguration(); 328b39f612d9791877bf0136fa7af9ae054092b9eabTadashi G. Takaoka final DisplayMetrics dm = mResources.getDisplayMetrics(); 3290a054dd1075d679385434ecef38a3d88c7551d7aTadashi G. Takaoka 3309b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka return new KeyboardId( 331af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka mResources.getResourceEntryName(xmlId), xmlId, locale, conf.orientation, 332af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka dm.widthPixels, mode, editorInfo, hasSettingsKey, f2KeyMode, noSettingsKey, 333af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka voiceKeyEnabled, hasShortcutKey); 3344199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka } 3354199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka 3363a2896c80475094f751ef447fc9c97028bfc2265Tadashi G. Takaoka public int getKeyboardMode() { 337cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka return mCurrentId != null ? mCurrentId.mMode : KeyboardId.MODE_TEXT; 338923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 3391679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka 3403a2896c80475094f751ef447fc9c97028bfc2265Tadashi G. Takaoka public boolean isAlphabetMode() { 341571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka return mCurrentId != null && mCurrentId.isAlphabetKeyboard(); 342923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 343923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 3441679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka public boolean isInputViewShown() { 34586e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka return mCurrentInputView != null && mCurrentInputView.isShown(); 3461679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka } 3471679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka 3481679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka public boolean isKeyboardAvailable() { 349c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka if (mKeyboardView != null) 350c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return mKeyboardView.getKeyboard() != null; 351b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 352b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 353b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka 354050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka public LatinKeyboard getLatinKeyboard() { 355c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka if (mKeyboardView != null) { 356c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka final Keyboard keyboard = mKeyboardView.getKeyboard(); 357050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka if (keyboard instanceof LatinKeyboard) 358050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka return (LatinKeyboard)keyboard; 359050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka } 360b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return null; 3611679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka } 3621679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka 363f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka public boolean isShiftedOrShiftLocked() { 364b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 365b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (latinKeyboard != null) 366f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka return latinKeyboard.isShiftedOrShiftLocked(); 367b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 3681679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka } 3691679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka 3701679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka public boolean isShiftLocked() { 371b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 372b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (latinKeyboard != null) 373b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return latinKeyboard.isShiftLocked(); 374b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return false; 3751679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka } 3761679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka 377f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka public boolean isAutomaticTemporaryUpperCase() { 378f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 379f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (latinKeyboard != null) 380f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka return latinKeyboard.isAutomaticTemporaryUpperCase(); 381f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka return false; 382f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } 383f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka 384f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka public boolean isManualTemporaryUpperCase() { 385f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 386f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (latinKeyboard != null) 387f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka return latinKeyboard.isManualTemporaryUpperCase(); 388f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka return false; 389f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } 390f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka 391d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka private boolean isManualTemporaryUpperCaseFromAuto() { 392d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 393d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka if (latinKeyboard != null) 394d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka return latinKeyboard.isManualTemporaryUpperCaseFromAuto(); 395d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka return false; 396d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka } 397d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka 398f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka private void setManualTemporaryUpperCase(boolean shifted) { 399b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 4000d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka if (latinKeyboard != null) { 4010d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka // On non-distinct multi touch panel device, we should also turn off the shift locked 4020d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka // state when shift key is pressed to go to normal mode. 4030d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka // On the other hand, on distinct multi touch panel device, turning off the shift locked 4040d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka // state with shift key pressing is handled by onReleaseShift(). 405101a00e3d4b1c29ef2ecdecd1b72b43efde7791aTadashi G. Takaoka if (!hasDistinctMultitouch() && !shifted && latinKeyboard.isShiftLocked()) { 4060d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka latinKeyboard.setShiftLocked(false); 4070d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka } 4080d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka if (latinKeyboard.setShifted(shifted)) { 409c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka mKeyboardView.invalidateAllKeys(); 4100d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka } 411979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 412979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 413979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 414b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka private void setShiftLocked(boolean shiftLocked) { 415b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka LatinKeyboard latinKeyboard = getLatinKeyboard(); 416b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (latinKeyboard != null && latinKeyboard.setShiftLocked(shiftLocked)) { 417c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka mKeyboardView.invalidateAllKeys(); 418b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 419979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 420979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 4210d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka /** 4220d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka * Toggle keyboard shift state triggered by user touch event. 4230d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka */ 424b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public void toggleShift() { 425b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mInputMethodService.mHandler.cancelUpdateShiftState(); 426f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 427f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "toggleShift:" 428f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 429f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " shiftKeyState=" + mShiftKeyState); 430b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (isAlphabetMode()) { 431f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka setManualTemporaryUpperCase(!isShiftedOrShiftLocked()); 432b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } else { 433b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka toggleShiftInSymbol(); 434b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 435b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 436b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka 437b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public void toggleCapsLock() { 438b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka mInputMethodService.mHandler.cancelUpdateShiftState(); 439f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 440f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "toggleCapsLock:" 441f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 442f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " shiftKeyState=" + mShiftKeyState); 443b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (isAlphabetMode()) { 444b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (isShiftLocked()) { 445f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // Shift key is long pressed while caps lock state, we will toggle back to normal 446f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // state. And mark as if shift key is released. 447f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka setShiftLocked(false); 448f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka mShiftKeyState.onRelease(); 449b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } else { 450b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka setShiftLocked(true); 451b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 452b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 453889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka } 454889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka 455f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka private void setAutomaticTemporaryUpperCase() { 456286a5bf1c68c8dd06ece9701a904593af2457586Ken Wakasa if (mKeyboardView == null) return; 457286a5bf1c68c8dd06ece9701a904593af2457586Ken Wakasa final Keyboard keyboard = mKeyboardView.getKeyboard(); 458e56e88beffe7afee3b41da4697304e1f4c031787Ken Wakasa if (keyboard == null) return; 459e56e88beffe7afee3b41da4697304e1f4c031787Ken Wakasa keyboard.setAutomaticTemporaryUpperCase(); 460286a5bf1c68c8dd06ece9701a904593af2457586Ken Wakasa mKeyboardView.invalidateAllKeys(); 461f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } 462f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka 4630d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka /** 4640d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka * Update keyboard shift state triggered by connected EditText status change. 4650d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka */ 466b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public void updateShiftState() { 46745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka final ShiftKeyState shiftKeyState = mShiftKeyState; 468f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 469f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "updateShiftState:" 470f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " autoCaps=" + mInputMethodService.getCurrentAutoCapsState() 471f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 472286a5bf1c68c8dd06ece9701a904593af2457586Ken Wakasa + " shiftKeyState=" + shiftKeyState 473286a5bf1c68c8dd06ece9701a904593af2457586Ken Wakasa + " isAlphabetMode=" + isAlphabetMode() 474286a5bf1c68c8dd06ece9701a904593af2457586Ken Wakasa + " isShiftLocked=" + isShiftLocked()); 47545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (isAlphabetMode()) { 47645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (!isShiftLocked() && !shiftKeyState.isIgnoring()) { 47745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (shiftKeyState.isReleasing() && mInputMethodService.getCurrentAutoCapsState()) { 47845911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka // Only when shift key is releasing, automatic temporary upper case will be set. 47945911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka setAutomaticTemporaryUpperCase(); 48045911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } else { 48145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka setManualTemporaryUpperCase(shiftKeyState.isMomentary()); 48245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } 483f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } 48445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka } else { 48545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka // In symbol keyboard mode, we should clear shift key state because only alphabet 48645911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka // keyboard has shift key. 48745911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka shiftKeyState.onRelease(); 488b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 489889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka } 490889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka 491b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka public void changeKeyboardMode() { 492f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 493f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "changeKeyboardMode:" 494f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 495f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " shiftKeyState=" + mShiftKeyState); 496b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka toggleKeyboardMode(); 497b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (isShiftLocked() && isAlphabetMode()) 498b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka setShiftLocked(true); 499b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka updateShiftState(); 500889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka } 501889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka 502e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka public void onPressShift(boolean withSliding) { 503b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (!isKeyboardAvailable()) 504b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return; 505f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka ShiftKeyState shiftKeyState = mShiftKeyState; 506f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 507f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "onPressShift:" 508f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 509e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka + " shiftKeyState=" + shiftKeyState + " sliding=" + withSliding); 510f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (isAlphabetMode()) { 511f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (isShiftLocked()) { 512f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // Shift key is pressed while caps lock state, we will treat this state as shifted 513f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // caps lock state and mark as if shift key pressed while normal state. 514f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka shiftKeyState.onPress(); 5156769c67987f323008647f5d029c02f8cc95272eeTadashi G. Takaoka setManualTemporaryUpperCase(true); 516f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } else if (isAutomaticTemporaryUpperCase()) { 517f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // Shift key is pressed while automatic temporary upper case, we have to move to 518f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // manual temporary upper case. 5196769c67987f323008647f5d029c02f8cc95272eeTadashi G. Takaoka shiftKeyState.onPress(); 520f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka setManualTemporaryUpperCase(true); 521f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } else if (isShiftedOrShiftLocked()) { 522f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // In manual upper case state, we just record shift key has been pressing while 523f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // shifted state. 524f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka shiftKeyState.onPressOnShifted(); 525f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } else { 526f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // In base layout, chording or manual temporary upper case mode is started. 527f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka shiftKeyState.onPress(); 5286769c67987f323008647f5d029c02f8cc95272eeTadashi G. Takaoka toggleShift(); 529f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka } 530b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } else { 531f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // In symbol mode, just toggle symbol and symbol more keyboard. 532f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka shiftKeyState.onPress(); 5336769c67987f323008647f5d029c02f8cc95272eeTadashi G. Takaoka toggleShift(); 534717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE; 535b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 536b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 537b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka 538e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka public void onReleaseShift(boolean withSliding) { 539b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (!isKeyboardAvailable()) 540b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka return; 541f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka ShiftKeyState shiftKeyState = mShiftKeyState; 542f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 543f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka Log.d(TAG, "onReleaseShift:" 544f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 545e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka + " shiftKeyState=" + shiftKeyState + " sliding=" + withSliding); 546b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka if (isAlphabetMode()) { 547f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (shiftKeyState.isMomentary()) { 548f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // After chording input while normal state. 549f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka toggleShift(); 550e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka } else if (isShiftLocked() && !shiftKeyState.isIgnoring() && !withSliding) { 551f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // Shift has been pressed without chording while caps lock state. 552f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka toggleCapsLock(); 553e541f03286189eebbc4a75615070e0e6f43ec37cTadashi G. Takaoka // To be able to turn off caps lock by "double tap" on shift key, we should ignore 554e541f03286189eebbc4a75615070e0e6f43ec37cTadashi G. Takaoka // the second tap of the "double tap" from now for a while because we just have 555e541f03286189eebbc4a75615070e0e6f43ec37cTadashi G. Takaoka // already turned off caps lock above. 556c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka mKeyboardView.startIgnoringDoubleTap(); 557e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka } else if (isShiftedOrShiftLocked() && shiftKeyState.isPressingOnShifted() 558e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka && !withSliding) { 559f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka // Shift has been pressed without chording while shifted state. 560b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka toggleShift(); 561e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka } else if (isManualTemporaryUpperCaseFromAuto() && shiftKeyState.isPressing() 562e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka && !withSliding) { 563d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka // Shift has been pressed without chording while manual temporary upper case 564d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka // transited from automatic temporary upper case. 565d01ae897d38d4e788e4f089e2b1d6d74655847c6Tadashi G. Takaoka toggleShift(); 566b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 567717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } else { 568717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // In symbol mode, snap back to the previous keyboard mode if the user chords the shift 569717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // key and another key, then releases the shift key. 570717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (mSwitchState == SWITCH_STATE_CHORDING_SYMBOL) { 571717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka toggleShift(); 572717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } 573b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 574f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka shiftKeyState.onRelease(); 575889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka } 576889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka 5776c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka public void onPressSymbol() { 578f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 5799e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka Log.d(TAG, "onPressSymbol:" 580f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 581f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " symbolKeyState=" + mSymbolKeyState); 582b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka changeKeyboardMode(); 5836c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka mSymbolKeyState.onPress(); 584717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL; 5856c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka } 5866c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka 5876c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka public void onReleaseSymbol() { 588f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka if (DEBUG_STATE) 5899e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka Log.d(TAG, "onReleaseSymbol:" 590f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 591f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka + " symbolKeyState=" + mSymbolKeyState); 5929e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Snap back to the previous keyboard mode if the user chords the mode change key and 593717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // another key, then releases the mode change key. 594717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (mSwitchState == SWITCH_STATE_CHORDING_ALPHA) { 595b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka changeKeyboardMode(); 596717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } 5976c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka mSymbolKeyState.onRelease(); 5986c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka } 5996c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka 6006c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka public void onOtherKeyPressed() { 60145911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka if (DEBUG_STATE) 60245911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka Log.d(TAG, "onOtherKeyPressed:" 60345911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() 60445911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka + " shiftKeyState=" + mShiftKeyState 60545911256fd4e32880e33c42259b19e8d7af70cb1Tadashi G. Takaoka + " symbolKeyState=" + mSymbolKeyState); 606f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka mShiftKeyState.onOtherKeyPressed(); 6076c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka mSymbolKeyState.onOtherKeyPressed(); 6086c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka } 6096c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka 6105f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka public void onCancelInput() { 6115f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // Snap back to the previous keyboard mode if the user cancels sliding input. 612717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (getPointerCount() == 1) { 613717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) { 614717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka changeKeyboardMode(); 615717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } else if (mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE) { 616717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka toggleShift(); 617717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } 618717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } 6195f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka } 6205f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka 621b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka private void toggleShiftInSymbol() { 6227e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka if (isAlphabetMode()) 6237e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka return; 6248b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka final LatinKeyboard keyboard; 62560ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka if (mCurrentId.equals(mSymbolsKeyboardId) 62660ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka || !mCurrentId.equals(mSymbolsShiftedKeyboardId)) { 62760ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka keyboard = getKeyboard(mSymbolsShiftedKeyboardId); 6287e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka } else { 62960ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka keyboard = getKeyboard(mSymbolsKeyboardId); 630923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 631050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka setKeyboard(keyboard); 632923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 633923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 634717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka public boolean isInMomentarySwitchState() { 635717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka return mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL 636717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka || mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE; 6379e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } 6389e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka 639cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka public boolean isVibrateAndSoundFeedbackRequired() { 640c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return mKeyboardView == null || !mKeyboardView.isInSlidingKeyInput(); 641cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka } 642cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka 6439e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka private int getPointerCount() { 644c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return mKeyboardView == null ? 0 : mKeyboardView.getPointerCount(); 6459e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } 6469e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka 647f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka private void toggleKeyboardMode() { 64860ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka if (mCurrentId.equals(mMainKeyboardId)) { 64960ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka setKeyboard(getKeyboard(mSymbolsKeyboardId)); 650b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } else { 65160ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka setKeyboard(getKeyboard(mMainKeyboardId)); 652b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 653b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 654b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani 655c8b9afe0378e3f33c3f83271bd1df9678a70c2a2Tadashi G. Takaoka public boolean hasDistinctMultitouch() { 656c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return mKeyboardView != null && mKeyboardView.hasDistinctMultitouch(); 657c8b9afe0378e3f33c3f83271bd1df9678a70c2a2Tadashi G. Takaoka } 658c8b9afe0378e3f33c3f83271bd1df9678a70c2a2Tadashi G. Takaoka 659717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static boolean isSpaceCharacter(int c) { 660717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka return c == Keyboard.CODE_SPACE || c == Keyboard.CODE_ENTER; 661717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } 662717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka 663717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka private static boolean isQuoteCharacter(int c) { 664717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // Apostrophe, quotation mark. 6650730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard if (c == Keyboard.CODE_SINGLE_QUOTE || c == Keyboard.CODE_DOUBLE_QUOTE) 666717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka return true; 667717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u2018: Left single quotation mark 668717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u2019: Right single quotation mark 669717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u201a: Single low-9 quotation mark 670717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u201b: Single high-reversed-9 quotation mark 671717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u201c: Left double quotation mark 672717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u201d: Right double quotation mark 673717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u201e: Double low-9 quotation mark 674717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u201f: Double high-reversed-9 quotation mark 675717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (c >= '\u2018' && c <= '\u201f') 676717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka return true; 677717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u00ab: Left-pointing double angle quotation mark 678717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // \u00bb: Right-pointing double angle quotation mark 679717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (c == '\u00ab' || c == '\u00bb') 680717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka return true; 681717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka return false; 682717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } 683717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka 684b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani /** 6859e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka * Updates state machine to figure out when to automatically snap back to the previous mode. 686b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani */ 687717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka public void onKey(int code) { 6889e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka if (DEBUG_STATE) 689717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka Log.d(TAG, "onKey: code=" + code + " switchState=" + mSwitchState 6909e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka + " pointers=" + getPointerCount()); 691717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka switch (mSwitchState) { 692717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: 6939e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Only distinct multi touch devices can be in this state. 6945f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // On non-distinct multi touch devices, mode change key is handled by 6955f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // {@link LatinIME#onCodeInput}, not by {@link LatinIME#onPress} and 696717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // {@link LatinIME#onRelease}. So, on such devices, {@link #mSwitchState} starts 697717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // from {@link #SWITCH_STATE_SYMBOL_BEGIN}, or {@link #SWITCH_STATE_ALPHA}, not from 698717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // {@link #SWITCH_STATE_MOMENTARY}. 699717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { 7009e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Detected only the mode change key has been pressed, and then released. 70160ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka if (mCurrentId.equals(mMainKeyboardId)) { 702717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_ALPHA; 70360ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka } else { 70460ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; 7059e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } 7069e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } else if (getPointerCount() == 1) { 7079e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Snap back to the previous keyboard mode if the user pressed the mode change key 7089e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // and slid to other key, then released the finger. 7095f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // If the user cancels the sliding input, snapping back to the previous keyboard 7105f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka // mode is handled by {@link #onCancelInput}. 7119e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka changeKeyboardMode(); 7129e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } else { 7139e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Chording input is being started. The keyboard mode will be snapped back to the 7149e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // previous mode in {@link onReleaseSymbol} when the mode change key is released. 715717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_CHORDING_ALPHA; 716717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } 717717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka break; 718717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE: 719717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (code == Keyboard.CODE_SHIFT) { 720717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // Detected only the shift key has been pressed on symbol layout, and then released. 721717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; 722717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } else if (getPointerCount() == 1) { 723717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // Snap back to the previous keyboard mode if the user pressed the shift key on 724717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // symbol mode and slid to other key, then released the finger. 725717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka toggleShift(); 726717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_SYMBOL; 727717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka } else { 728717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // Chording input is being started. The keyboard mode will be snapped back to the 729717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka // previous mode in {@link onReleaseShift} when the shift key is released. 730717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_CHORDING_SYMBOL; 7319e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka } 7329e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka break; 733717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka case SWITCH_STATE_SYMBOL_BEGIN: 734717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (!isSpaceCharacter(code) && code >= 0) { 735717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka mSwitchState = SWITCH_STATE_SYMBOL; 736b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 7370b4757604de15bfe66c10e9cdf01da6d437c6082Ken Wakasa // Snap back to alpha keyboard mode immediately if user types a quote character. 7380b4757604de15bfe66c10e9cdf01da6d437c6082Ken Wakasa if (isQuoteCharacter(code)) { 7390b4757604de15bfe66c10e9cdf01da6d437c6082Ken Wakasa changeKeyboardMode(); 7400b4757604de15bfe66c10e9cdf01da6d437c6082Ken Wakasa } 741b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka break; 742717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka case SWITCH_STATE_SYMBOL: 743717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka case SWITCH_STATE_CHORDING_SYMBOL: 7449e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka // Snap back to alpha keyboard mode if user types one or more non-space/enter 7450b4757604de15bfe66c10e9cdf01da6d437c6082Ken Wakasa // characters followed by a space/enter or a quote character. 746717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka if (isSpaceCharacter(code) || isQuoteCharacter(code)) { 747b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka changeKeyboardMode(); 748b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka } 749b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka break; 750b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani } 751923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 752979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 753c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka public LatinKeyboardView getKeyboardView() { 754c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka return mKeyboardView; 755979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 756979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 757c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka public View onCreateInputView() { 758f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka return createInputView(mThemeIndex, true); 759979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 760979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 761f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka private View createInputView(final int newThemeIndex, final boolean forceRecreate) { 762f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka if (mCurrentInputView != null && mThemeIndex == newThemeIndex && !forceRecreate) 763f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka return mCurrentInputView; 764f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka 765f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka if (mKeyboardView != null) { 766f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka mKeyboardView.closing(); 767f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka } 768f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka 7695a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka final int oldThemeIndex = mThemeIndex; 770f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka Utils.GCUtils.getInstance().reset(); 771f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka boolean tryGC = true; 772f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { 773f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka try { 7745a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka setContextThemeWrapper(mInputMethodService, newThemeIndex); 7755a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka mCurrentInputView = LayoutInflater.from(mThemeContext).inflate( 77613a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka R.layout.input_view, null); 777f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka tryGC = false; 778f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka } catch (OutOfMemoryError e) { 779f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka Log.w(TAG, "load keyboard failed: " + e); 7805a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka tryGC = Utils.GCUtils.getInstance().tryGCOrWait( 7815a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka oldThemeIndex + "," + newThemeIndex, e); 782f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka } catch (InflateException e) { 783f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka Log.w(TAG, "load keyboard failed: " + e); 7845a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka tryGC = Utils.GCUtils.getInstance().tryGCOrWait( 7855a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka oldThemeIndex + "," + newThemeIndex, e); 786979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 787979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 788f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka 789c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka mKeyboardView = (LatinKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view); 7905a7a696aff6718d4e0250c394a9d01cbf2a16916Tadashi G. Takaoka mKeyboardView.setKeyboardActionListener(mInputMethodService); 7915ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 7925ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette // This always needs to be set since the accessibility state can 7935ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette // potentially change without the input view being re-created. 7945ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette AccessibleKeyboardViewProxy.setView(mKeyboardView); 7955ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette 796f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka return mCurrentInputView; 7978d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka } 7988d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka 799f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka private void postSetInputView(final View newInputView) { 800979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mInputMethodService.mHandler.post(new Runnable() { 8018d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka @Override 802979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public void run() { 803f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka if (newInputView != null) { 804f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka mInputMethodService.setInputView(newInputView); 805979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 806979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mInputMethodService.updateInputViewShown(); 8078d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka } 8088d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka }); 809979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 810979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 8118d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka @Override 812979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { 813979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (PREF_KEYBOARD_LAYOUT.equals(key)) { 8142ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa final int themeIndex = getKeyboardThemeIndex(mInputMethodService, sharedPreferences); 8152ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa postSetInputView(createInputView(themeIndex, false)); 8162ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa } else if (Settings.PREF_SHOW_SETTINGS_KEY.equals(key)) { 817f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka postSetInputView(createInputView(mThemeIndex, true)); 818979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 819979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 820979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 8211b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka public void onAutoCorrectionStateChanged(boolean isAutoCorrection) { 8225e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka if (mIsAutoCorrectionActive != isAutoCorrection) { 8231b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka mIsAutoCorrectionActive = isAutoCorrection; 8245e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka final LatinKeyboard keyboard = getLatinKeyboard(); 8255e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka if (keyboard != null && keyboard.needsAutoCorrectionSpacebarLed()) { 8265e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka final Key invalidatedKey = keyboard.onAutoCorrectionStateChanged(isAutoCorrection); 827c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka final LatinKeyboardView keyboardView = getKeyboardView(); 8285e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka if (keyboardView != null) 8295e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka keyboardView.invalidateKey(invalidatedKey); 8305e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka } 83141feaaadb758a8b31d3e436063b4b5faed104d4dsatok } 83241feaaadb758a8b31d3e436063b4b5faed104d4dsatok } 8331508c0e84f0cd93ab6f5d46fea5026e833f299bcKen Wakasa 8342ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa private static int getF2KeyMode(boolean settingsKeyEnabled, boolean noSettingsKey) { 8352ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa if (noSettingsKey) { 8362ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa // Never shows the Settings key 837cd96a691b14b384face577d907f6c1aa33b47233Tadashi G. Takaoka return KeyboardId.F2KEY_MODE_SHORTCUT_IME; 838cd96a691b14b384face577d907f6c1aa33b47233Tadashi G. Takaoka } 8392ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa 8402ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa if (settingsKeyEnabled) { 8412ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa return KeyboardId.F2KEY_MODE_SETTINGS; 8422ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa } else { 8432ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa // It should be alright to fall back to the Settings key on 7-inch layouts 8442ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa // even when the Settings key is not explicitly enabled. 8452ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa return KeyboardId.F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS; 8462ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa } 847cd96a691b14b384face577d907f6c1aa33b47233Tadashi G. Takaoka } 848923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 849