KeyboardSwitcher.java revision cf58f53a1ab53b427a3d9784502b47ba1833b018
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;
32b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyboardState;
33f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaokaimport com.android.inputmethod.latin.InputView;
34571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.LatinIME;
35571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.LatinImeLogger;
36ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalardimport com.android.inputmethod.latin.LocaleUtils;
37571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.R;
385cd87e1b1c4258e8d016518914eccfbb4437caceTadashi G. Takaokaimport com.android.inputmethod.latin.Settings;
39571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.SubtypeSwitcher;
405cd87e1b1c4258e8d016518914eccfbb4437caceTadashi G. Takaokaimport com.android.inputmethod.latin.Utils;
415a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka
42681b676b0aecb30e644f25550018ce2b6cea3e15Tadashi G. Takaokaimport java.lang.ref.SoftReference;
4312659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaokaimport java.util.HashMap;
4412659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaokaimport java.util.Locale;
4512659d4c0ce04aaf3d8479e44f9230881b964000Tadashi G. Takaoka
46eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaokapublic class KeyboardSwitcher implements KeyboardState.SwitchActions,
47eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka        SharedPreferences.OnSharedPreferenceChangeListener {
48c25e07d21261583d0eeca5aa0fb6e3ffe93dc603Tadashi G. Takaoka    private static final String TAG = KeyboardSwitcher.class.getSimpleName();
49c25e07d21261583d0eeca5aa0fb6e3ffe93dc603Tadashi G. Takaoka    private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG;
50f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka    public static final boolean DEBUG_STATE = false;
51923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
522d9722e46c774d51c834c3a8b11261a2a22e09d3Ken Wakasa    public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20110916";
5305ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka    private static final int[] KEYBOARD_THEMES = {
5413a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka        R.style.KeyboardTheme,
5513a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka        R.style.KeyboardTheme_HighContrast,
5613a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka        R.style.KeyboardTheme_Stone,
5713a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka        R.style.KeyboardTheme_Stone_Bold,
5813a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka        R.style.KeyboardTheme_Gingerbread,
599116bf18f9c83084f9d451e2e709eff32db27d36Tadashi G. Takaoka        R.style.KeyboardTheme_IceCreamSandwich,
6075fde6489039c09056fb5e64d39630ece5ad57cfTadashi G. Takaoka    };
61979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
620ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok    private SubtypeSwitcher mSubtypeSwitcher;
6327d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa    private SharedPreferences mPrefs;
640ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok
65f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka    private InputView mCurrentInputView;
66c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka    private LatinKeyboardView mKeyboardView;
670ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok    private LatinIME mInputMethodService;
680a054dd1075d679385434ecef38a3d88c7551d7aTadashi G. Takaoka    private String mPackageName;
690a054dd1075d679385434ecef38a3d88c7551d7aTadashi G. Takaoka    private Resources mResources;
7031adfa78e2edae188edb05e869f9f68798857582satok
71b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka    private KeyboardState mState;
726ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka    private static final int UNSHIFT = 0;
736ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka    private static final int MANUAL_SHIFT = 1;
746ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka    private static final int AUTOMATIC_SHIFT = 2;
75889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka
7660ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka    private KeyboardId mMainKeyboardId;
7760ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka    private KeyboardId mSymbolsKeyboardId;
7860ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka    private KeyboardId mSymbolsShiftedKeyboardId;
79353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger
80353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger    private KeyboardId mCurrentId;
818b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka    private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache =
828b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka            new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
83466741d8a78965b8509bf527344f289e50873092Mike LeBeau
841b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka    /** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of
8541feaaadb758a8b31d3e436063b4b5faed104d4dsatok     * what user actually typed. */
861b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka    private boolean mIsAutoCorrectionActive;
879e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka
885a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka    private int mThemeIndex = -1;
895a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka    private Context mThemeContext;
90979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
910ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok    private static final KeyboardSwitcher sInstance = new KeyboardSwitcher();
920ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok
930ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok    public static KeyboardSwitcher getInstance() {
940ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok        return sInstance;
950ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok    }
960ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok
970ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok    private KeyboardSwitcher() {
98e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka        // Intentional empty constructor for singleton.
990ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok    }
1000ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok
10127d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa    public static void init(LatinIME ims, SharedPreferences prefs) {
102364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka        sInstance.initInternal(ims, prefs);
103364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka    }
104364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka
105364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka    private void initInternal(LatinIME ims, SharedPreferences prefs) {
106364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka        mInputMethodService = ims;
107364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka        mPackageName = ims.getPackageName();
108364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka        mResources = ims.getResources();
109364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka        mPrefs = prefs;
110364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka        mSubtypeSwitcher = SubtypeSwitcher.getInstance();
111eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka        mState = new KeyboardState(this);
112364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka        setContextThemeWrapper(ims, getKeyboardThemeIndex(ims, prefs));
113364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka        prefs.registerOnSharedPreferenceChangeListener(this);
1145a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka    }
115979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
1165a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka    private static int getKeyboardThemeIndex(Context context, SharedPreferences prefs) {
1175a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka        final String defaultThemeId = context.getString(R.string.config_default_keyboard_theme_id);
1182d9722e46c774d51c834c3a8b11261a2a22e09d3Ken Wakasa        final String themeId = prefs.getString(PREF_KEYBOARD_LAYOUT, defaultThemeId);
11905ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka        try {
1205a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka            final int themeIndex = Integer.valueOf(themeId);
1215a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka            if (themeIndex >= 0 && themeIndex < KEYBOARD_THEMES.length)
1225a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka                return themeIndex;
12305ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka        } catch (NumberFormatException e) {
1245a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka            // Format error, keyboard theme is default to 0.
1255a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka        }
1265a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka        Log.w(TAG, "Illegal keyboard theme in preference: " + themeId + ", default to 0");
1275a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka        return 0;
1285a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka    }
1295a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka
1305a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka    private void setContextThemeWrapper(Context context, int themeIndex) {
1315a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka        if (mThemeIndex != themeIndex) {
1325a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka            mThemeIndex = themeIndex;
1335a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka            mThemeContext = new ContextThemeWrapper(context, KEYBOARD_THEMES[themeIndex]);
1345a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka            mKeyboardCache.clear();
13505ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka        }
136979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    }
137979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
1382ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa    public void loadKeyboard(EditorInfo editorInfo, Settings.Values settingsValues) {
139979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        try {
1402ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa            mMainKeyboardId = getKeyboardId(editorInfo, false, false, settingsValues);
1412ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa            mSymbolsKeyboardId = getKeyboardId(editorInfo, true, false, settingsValues);
1422ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa            mSymbolsShiftedKeyboardId = getKeyboardId(editorInfo, true, true, settingsValues);
143eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka            mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols));
144eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka            mPrevMainKeyboardWasShiftLocked = false;
145cf58f53a1ab53b427a3d9784502b47ba1833b018Tadashi G. Takaoka            mState.onRestoreKeyboardState();
146979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        } catch (RuntimeException e) {
14760ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka            Log.w(TAG, "loading keyboard failed: " + mMainKeyboardId, e);
14860ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka            LatinImeLogger.logOnException(mMainKeyboardId.toString(), e);
149979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        }
150353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger    }
151353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger
15259f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka    public void saveKeyboardState() {
1532e263b70d5769b52cba4a002e44dbf81db5de7f8Tadashi G. Takaoka        if (mCurrentId != null) {
154cf58f53a1ab53b427a3d9784502b47ba1833b018Tadashi G. Takaoka            mState.onSaveKeyboardState(isAlphabetMode(), isSymbolShifted());
1552e263b70d5769b52cba4a002e44dbf81db5de7f8Tadashi G. Takaoka        }
156055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka    }
157055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka
158055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka    public void onFinishInputView() {
159055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka        mIsAutoCorrectionActive = false;
160055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka    }
161055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka
162c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka    public void onHideWindow() {
163c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka        mIsAutoCorrectionActive = false;
164c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka    }
165c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka
166055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka    private void setKeyboard(final Keyboard keyboard) {
167c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka        final Keyboard oldKeyboard = mKeyboardView.getKeyboard();
168055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka        mKeyboardView.setKeyboard(keyboard);
169f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka        mCurrentInputView.setKeyboardGeometry(keyboard.mTopPadding);
170055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka        mCurrentId = keyboard.mId;
171eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka        mState.onSetKeyboard(isAlphabetMode());
172055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka        updateShiftLockState(keyboard);
173c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka        mKeyboardView.setKeyPreviewPopupEnabled(
1740a054dd1075d679385434ecef38a3d88c7551d7aTadashi G. Takaoka                Settings.Values.isKeyPreviewPopupEnabled(mPrefs, mResources),
1750a054dd1075d679385434ecef38a3d88c7551d7aTadashi G. Takaoka                Settings.Values.getKeyPreviewPopupDismissDelay(mPrefs, mResources));
176050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka        final boolean localeChanged = (oldKeyboard == null)
177055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka                || !keyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale);
178050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka        mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged);
179286a5bf1c68c8dd06ece9701a904593af2457586Ken Wakasa        updateShiftState();
180353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger    }
181353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger
182055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka    private void updateShiftLockState(Keyboard keyboard) {
183055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka        if (mCurrentId.equals(mSymbolsShiftedKeyboardId)) {
184055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka            // Symbol keyboard may have an ALT key that has a caps lock style indicator (a.k.a.
185055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka            // sticky shift key). To show or dismiss the indicator, we need to call setShiftLocked()
186055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka            // that takes care of the current keyboard having such ALT key or not.
187055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka            keyboard.setShiftLocked(keyboard.hasShiftLockKey());
188055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka        } else if (mCurrentId.equals(mSymbolsKeyboardId)) {
189055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka            // Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the
190055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka            // indicator, we need to call setShiftLocked(false).
191055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka            keyboard.setShiftLocked(false);
192055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka        }
193055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka    }
194055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka
195353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger    private LatinKeyboard getKeyboard(KeyboardId id) {
1968b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka        final SoftReference<LatinKeyboard> ref = mKeyboardCache.get(id);
197681b676b0aecb30e644f25550018ce2b6cea3e15Tadashi G. Takaoka        LatinKeyboard keyboard = (ref == null) ? null : ref.get();
198681b676b0aecb30e644f25550018ce2b6cea3e15Tadashi G. Takaoka        if (keyboard == null) {
199ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard            final Locale savedLocale = LocaleUtils.setSystemLocale(mResources, id.mLocale);
2008da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka            try {
201294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima                final LatinKeyboard.Builder builder = new LatinKeyboard.Builder(mThemeContext);
202294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima                builder.load(id);
203294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima                builder.setTouchPositionCorrectionEnabled(
204294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima                        mSubtypeSwitcher.currentSubtypeContainsExtraValueKey(
205294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima                                LatinIME.SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION));
206294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima                keyboard = builder.build();
2078da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka            } finally {
208ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963Jean Chalard                LocaleUtils.setSystemLocale(mResources, savedLocale);
2098da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka            }
2108b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka            mKeyboardCache.put(id, new SoftReference<LatinKeyboard>(keyboard));
2118da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka
2128da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka            if (DEBUG_CACHE) {
2138b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka                Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": "
21463584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka                        + ((ref == null) ? "LOAD" : "GCed") + " id=" + id
21563584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka                        + " theme=" + Keyboard.themeName(keyboard.mThemeId));
2168da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka            }
217e896d31bb92146379c8b7c0050ee05eec0830317Tadashi G. Takaoka        } else if (DEBUG_CACHE) {
21863584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka            Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT  id=" + id
21963584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka                    + " theme=" + Keyboard.themeName(keyboard.mThemeId));
220353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger        }
2218b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka
2221b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka        keyboard.onAutoCorrectionStateChanged(mIsAutoCorrectionActive);
22373c02390d31bbf32b78763db66b04004666fb5a3Tadashi G. Takaoka        keyboard.setShiftLocked(false);
2248b00bc4f3281c229ee830f34a78c0ec287902c3fTadashi G. Takaoka        keyboard.setShifted(false);
225de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka        // If the cached keyboard had been switched to another keyboard while the language was
226de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka        // displayed on its spacebar, it might have had arbitrary text fade factor. In such case,
2275cd87e1b1c4258e8d016518914eccfbb4437caceTadashi G. Takaoka        // we should reset the text fade factor. It is also applicable to shortcut key.
228de0c8874a4eb1250e8439d9e4e1badca88316670Tadashi G. Takaoka        keyboard.setSpacebarTextFadeFactor(0.0f, null);
2294503e2ea9853c1573f60903d8639d82e39e07c56Tadashi G. Takaoka        keyboard.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady(), null);
230681b676b0aecb30e644f25550018ce2b6cea3e15Tadashi G. Takaoka        return keyboard;
231353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger    }
232353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger
2332ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa    private KeyboardId getKeyboardId(EditorInfo editorInfo, final boolean isSymbols,
2342ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa            final boolean isShift, Settings.Values settingsValues) {
2352ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa        final int mode = Utils.getKeyboardMode(editorInfo);
23659c9930ca98f68aeb6b0b9dc19e29666b8fb152aTadashi G. Takaoka        final int xmlId;
23760ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka        switch (mode) {
23860ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka        case KeyboardId.MODE_PHONE:
23960ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka            xmlId = (isSymbols && isShift) ? R.xml.kbd_phone_shift : R.xml.kbd_phone;
24060ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka            break;
24160ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka        case KeyboardId.MODE_NUMBER:
24260ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka            xmlId = R.xml.kbd_number;
24360ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka            break;
24460ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka        default:
24560ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka            if (isSymbols) {
24660ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka                xmlId = isShift ? R.xml.kbd_symbols_shift : R.xml.kbd_symbols;
2472c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka            } else {
2482c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka                xmlId = R.xml.kbd_qwerty;
2492c60d6e28ecf7d6f7e97a504ebfa97e286d931edTadashi G. Takaoka            }
25060ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka            break;
251923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
25260ccbe16eea5ce9a874835850f257b3c88295022Tadashi G. Takaoka
253cee174b8ccb47ccddc8a8a7e88a9c617f9b5e766Ken Wakasa        final boolean settingsKeyEnabled = settingsValues.isSettingsKeyEnabled();
254ab72a97d7ce44230a0c824797d1675a5ca354a56Tadashi G. Takaoka        @SuppressWarnings("deprecation")
25573e716f20284f929b2c0323c9e4759efe558de9dTadashi G. Takaoka        final boolean noMicrophone = Utils.inPrivateImeOptions(
25673e716f20284f929b2c0323c9e4759efe558de9dTadashi G. Takaoka                mPackageName, LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo)
25773e716f20284f929b2c0323c9e4759efe558de9dTadashi G. Takaoka                || Utils.inPrivateImeOptions(
25873e716f20284f929b2c0323c9e4759efe558de9dTadashi G. Takaoka                        null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo);
25973e716f20284f929b2c0323c9e4759efe558de9dTadashi G. Takaoka        final boolean voiceKeyEnabled = settingsValues.isVoiceKeyEnabled(editorInfo)
26073e716f20284f929b2c0323c9e4759efe558de9dTadashi G. Takaoka                && !noMicrophone;
2612ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa        final boolean voiceKeyOnMain = settingsValues.isVoiceKeyOnMain();
2620a054dd1075d679385434ecef38a3d88c7551d7aTadashi G. Takaoka        final boolean noSettingsKey = Utils.inPrivateImeOptions(
2632ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa                mPackageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, editorInfo);
2642ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa        final boolean hasSettingsKey = settingsKeyEnabled && !noSettingsKey;
2652ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa        final int f2KeyMode = getF2KeyMode(settingsKeyEnabled, noSettingsKey);
266c3afe2c244c14ed0f8a355fe608b3402e3656330Tadashi G. Takaoka        final boolean hasShortcutKey = voiceKeyEnabled && (isSymbols != voiceKeyOnMain);
267af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka        final boolean forceAscii = Utils.inPrivateImeOptions(
268af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka                mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, editorInfo);
269af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka        final boolean asciiCapable = mSubtypeSwitcher.currentSubtypeContainsExtraValueKey(
270af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka                LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE);
271af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka        final Locale locale = (forceAscii && !asciiCapable)
272af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka                ? Locale.US : mSubtypeSwitcher.getInputLocale();
2732ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa        final Configuration conf = mResources.getConfiguration();
274b39f612d9791877bf0136fa7af9ae054092b9eabTadashi G. Takaoka        final DisplayMetrics dm = mResources.getDisplayMetrics();
2750a054dd1075d679385434ecef38a3d88c7551d7aTadashi G. Takaoka
2769b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka        return new KeyboardId(
277af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka                mResources.getResourceEntryName(xmlId), xmlId, locale, conf.orientation,
278af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka                dm.widthPixels, mode, editorInfo, hasSettingsKey, f2KeyMode, noSettingsKey,
279af52c0ea04c6563feaa6ea7dbac5dd87c2a48cc6Tadashi G. Takaoka                voiceKeyEnabled, hasShortcutKey);
2804199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka    }
2814199e29a7d796191d3e13ef07e6e80e91834fe7aTadashi G. Takaoka
2823a2896c80475094f751ef447fc9c97028bfc2265Tadashi G. Takaoka    public int getKeyboardMode() {
283cb97c2f1407364b24dc1a54226481a55501d1533Tadashi G. Takaoka        return mCurrentId != null ? mCurrentId.mMode : KeyboardId.MODE_TEXT;
284923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
2851679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka
2863a2896c80475094f751ef447fc9c97028bfc2265Tadashi G. Takaoka    public boolean isAlphabetMode() {
287571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka        return mCurrentId != null && mCurrentId.isAlphabetKeyboard();
288923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
289923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
2901679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka    public boolean isInputViewShown() {
29186e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka        return mCurrentInputView != null && mCurrentInputView.isShown();
2921679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka    }
2931679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka
2941679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka    public boolean isKeyboardAvailable() {
295c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka        if (mKeyboardView != null)
296c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka            return mKeyboardView.getKeyboard() != null;
297b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka        return false;
298b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka    }
299b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka
300050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka    public LatinKeyboard getLatinKeyboard() {
301c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka        if (mKeyboardView != null) {
302c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka            final Keyboard keyboard = mKeyboardView.getKeyboard();
303050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka            if (keyboard instanceof LatinKeyboard)
304050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka                return (LatinKeyboard)keyboard;
305050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka        }
306b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka        return null;
3071679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka    }
3081679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka
309f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka    public boolean isShiftedOrShiftLocked() {
310c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka        return mState.isShiftedOrShiftLocked();
311f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka    }
312f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka
313f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka    public boolean isManualTemporaryUpperCase() {
314c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka        return mState.isManualTemporaryUpperCase();
315f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka    }
316f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka
317eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    // Implements {@link KeyboardState.SwitchActions}.
318eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    @Override
319eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    public void setShifted(int shiftMode) {
320f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka        mInputMethodService.mHandler.cancelUpdateShiftState();
321b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka        LatinKeyboard latinKeyboard = getLatinKeyboard();
3226ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka        if (latinKeyboard == null)
3236ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka            return;
3246ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka        if (shiftMode == AUTOMATIC_SHIFT) {
325c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka            mState.setAutomaticTemporaryUpperCase();
3266ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka            latinKeyboard.setAutomaticTemporaryUpperCase();
3276ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka        } else {
3286ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka            final boolean shifted = (shiftMode == MANUAL_SHIFT);
3290d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka            // On non-distinct multi touch panel device, we should also turn off the shift locked
3300d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka            // state when shift key is pressed to go to normal mode.
3316ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka            // On the other hand, on distinct multi touch panel device, turning off the shift
3326ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka            // locked state with shift key pressing is handled by onReleaseShift().
333101a00e3d4b1c29ef2ecdecd1b72b43efde7791aTadashi G. Takaoka            if (!hasDistinctMultitouch() && !shifted && latinKeyboard.isShiftLocked()) {
334c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka                mState.setShiftLocked(false);
3350d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka                latinKeyboard.setShiftLocked(false);
3360d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka            }
337c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka            mState.setShifted(shifted);
3384f7f61730cbd45871c1e9044da84b494831f97c3Tadashi G. Takaoka            latinKeyboard.setShifted(shifted);
339979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        }
3404f7f61730cbd45871c1e9044da84b494831f97c3Tadashi G. Takaoka        mKeyboardView.invalidateAllKeys();
341979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    }
342979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
343eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    // Implements {@link KeyboardState.SwitchActions}.
344eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    @Override
345eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    public void setShiftLocked(boolean shiftLocked) {
346f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka        mInputMethodService.mHandler.cancelUpdateShiftState();
347b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka        LatinKeyboard latinKeyboard = getLatinKeyboard();
348c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka        if (latinKeyboard == null)
349c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka            return;
350c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka        mState.setShiftLocked(shiftLocked);
351c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka        latinKeyboard.setShiftLocked(shiftLocked);
352c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka        mKeyboardView.invalidateAllKeys();
353f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka        if (!shiftLocked) {
354f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka            // To be able to turn off caps lock by "double tap" on shift key, we should ignore
355f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka            // the second tap of the "double tap" from now for a while because we just have
356f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka            // already turned off caps lock above.
357f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka            mKeyboardView.startIgnoringDoubleTap();
358f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka        }
359979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    }
360979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
3610d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka    /**
3620d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka     * Toggle keyboard shift state triggered by user touch event.
3630d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka     */
364b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka    public void toggleShift() {
365b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka        if (DEBUG_STATE) {
366c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka            Log.d(TAG, "toggleShift: " + mState);
367b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka        }
368b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka        if (isAlphabetMode()) {
369c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka            setShifted(mState.isShiftedOrShiftLocked() ? UNSHIFT : MANUAL_SHIFT);
370b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka        } else {
3718a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka            toggleShiftInSymbols();
372b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka        }
373b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka    }
374b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka
375b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka    public void toggleCapsLock() {
376b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka        if (DEBUG_STATE) {
377c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka            Log.d(TAG, "toggleCapsLock: " + mState);
378b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka        }
379b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka        if (isAlphabetMode()) {
380c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka            if (mState.isShiftLocked()) {
381f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka                setShiftLocked(false);
382f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka                // TODO: Remove this.
383f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka                // Shift key is long pressed while caps lock state, we will toggle back to normal
384f27364600c742509b48857e6b8f17312033e0dc7Tadashi G. Takaoka                // state. And mark as if shift key is released.
385f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka                mState.onReleaseCapsLock();
386b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka            } else {
387b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka                setShiftLocked(true);
388b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka            }
389b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka        }
390889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka    }
391889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka
3928a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka    public void toggleKeyboardMode() {
39346831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka        if (DEBUG_STATE) {
3948a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka            Log.d(TAG, "toggleKeyboard: " + mState);
39546831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka        }
3968a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka        toggleAlphabetAndSymbols();
39746831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka    }
39846831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka
3990d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka    /**
4000d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka     * Update keyboard shift state triggered by connected EditText status change.
4010d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka     */
402b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka    public void updateShiftState() {
403b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka        if (DEBUG_STATE) {
404c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka            Log.d(TAG, "updateShiftState: " + mState
405c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka                    + " autoCaps=" + mInputMethodService.getCurrentAutoCapsState());
406b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka        }
407eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka        mState.onUpdateShiftState(isAlphabetMode(), mInputMethodService.getCurrentAutoCapsState());
408889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka    }
409889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka
410e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka    public void onPressShift(boolean withSliding) {
411b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka        if (!isKeyboardAvailable())
412b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka            return;
413b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka        if (DEBUG_STATE) {
414c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka            Log.d(TAG, "onPressShift: " + mState + " sliding=" + withSliding);
415b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka        }
416eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka        mState.onPressShift(isAlphabetMode(), isSymbolShifted());
417b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka    }
418b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka
419e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka    public void onReleaseShift(boolean withSliding) {
420b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka        if (!isKeyboardAvailable())
421b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka            return;
422b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka        if (DEBUG_STATE) {
423c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka            Log.d(TAG, "onReleaseShift: " + mState + " sliding=" + withSliding);
424b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka        }
425eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka        mState.onReleaseShift(isAlphabetMode(), isSymbolShifted(), withSliding);
426889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka    }
427889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka
4286c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka    public void onPressSymbol() {
429b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka        if (DEBUG_STATE) {
430c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka            Log.d(TAG, "onPressSymbol: " + mState);
431b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka        }
432eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka        mState.onPressSymbol(isAlphabetMode());
4336c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka    }
4346c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka
4356c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka    public void onReleaseSymbol() {
436b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka        if (DEBUG_STATE) {
437c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka            Log.d(TAG, "onReleaseSymbol: " + mState);
438717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka        }
439eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka        mState.onReleaseSymbol(isAlphabetMode());
4406c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka    }
4416c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka
4426c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka    public void onOtherKeyPressed() {
443b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka        if (DEBUG_STATE) {
444c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka            Log.d(TAG, "onOtherKeyPressed: " + mState);
445b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka        }
446b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka        mState.onOtherKeyPressed();
4476c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka    }
4486c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka
4495f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka    public void onCancelInput() {
450eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka        mState.onCancelInput(isAlphabetMode(), isSymbolShifted(), isSinglePointer());
4515f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka    }
4525f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka
453b300dbbd39b1aed738028fb538aa935a7fbd2e37Tadashi G. Takaoka    // TODO: Move this variable to KeyboardState.
45446831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka    private boolean mPrevMainKeyboardWasShiftLocked;
45546831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka
456eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    // Implements {@link KeyboardState.SwitchActions}.
457eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    @Override
458eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    public void setSymbolsKeyboard() {
4598a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka        mPrevMainKeyboardWasShiftLocked = mState.isShiftLocked();
4608a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka        setKeyboard(getKeyboard(mSymbolsKeyboardId));
4618a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka    }
4628a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka
463eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    // Implements {@link KeyboardState.SwitchActions}.
464eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    @Override
465eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    public void setAlphabetKeyboard() {
4668a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka        setKeyboard(getKeyboard(mMainKeyboardId));
4678a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka        setShiftLocked(mPrevMainKeyboardWasShiftLocked);
4688a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka        mPrevMainKeyboardWasShiftLocked = false;
4698a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka    }
4708a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka
471eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    // TODO: Remove this method and merge into toggleKeyboardMode().
4728a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka    private void toggleAlphabetAndSymbols() {
4738a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka        if (isAlphabetMode()) {
4748a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka            setSymbolsKeyboard();
47546831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka        } else {
4768a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka            setAlphabetKeyboard();
47746831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka        }
47846831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka    }
47946831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka
4808a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka    private boolean isSymbolShifted() {
4818a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka        return mCurrentId != null && mCurrentId.equals(mSymbolsShiftedKeyboardId);
4828a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka    }
4838a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka
484eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    // Implements {@link KeyboardState.SwitchActions}.
485eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    @Override
486eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    public void setSymbolsShiftedKeyboard() {
4878a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka        setKeyboard(getKeyboard(mSymbolsShiftedKeyboardId));
4888a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka    }
4898a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka
490eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    // TODO: Remove this method and merge into toggleShift().
4918a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka    private void toggleShiftInSymbols() {
4928a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka        if (isSymbolShifted()) {
4938a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka            setSymbolsKeyboard();
4947e1f5a2d5a96c74691b3b09fa986efb7161e5a12Tadashi G. Takaoka        } else {
4958a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka            setSymbolsShiftedKeyboard();
496923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
497923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
498923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
499717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka    public boolean isInMomentarySwitchState() {
500eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka        return mState.isInMomentarySwitchState();
5019e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka    }
5029e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka
503cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka    public boolean isVibrateAndSoundFeedbackRequired() {
504416ee19d330f08e329cce4fd7cb66003cfb64f4aTadashi G. Takaoka        return mKeyboardView != null && !mKeyboardView.isInSlidingKeyInput();
505cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka    }
506cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka
50746831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka    private boolean isSinglePointer() {
50846831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka        return mKeyboardView != null && mKeyboardView.getPointerCount() == 1;
509b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani    }
510b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani
511c8b9afe0378e3f33c3f83271bd1df9678a70c2a2Tadashi G. Takaoka    public boolean hasDistinctMultitouch() {
512c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka        return mKeyboardView != null && mKeyboardView.hasDistinctMultitouch();
513c8b9afe0378e3f33c3f83271bd1df9678a70c2a2Tadashi G. Takaoka    }
514c8b9afe0378e3f33c3f83271bd1df9678a70c2a2Tadashi G. Takaoka
515b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani    /**
5169e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka     * Updates state machine to figure out when to automatically snap back to the previous mode.
517b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani     */
518eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    public void onCodeInput(int code) {
51946831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka        if (DEBUG_STATE) {
520eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka            Log.d(TAG, "onCodeInput: code=" + code + " isSinglePointer=" + isSinglePointer()
521eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka                    + " " + mState);
522b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani        }
523eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka        mState.onCodeInput(isAlphabetMode(), isSymbolShifted(), code, isSinglePointer());
524923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
525979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
526c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka    public LatinKeyboardView getKeyboardView() {
527c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka        return mKeyboardView;
528979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    }
529979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
530c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka    public View onCreateInputView() {
531f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka        return createInputView(mThemeIndex, true);
532979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    }
533979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
534f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka    private View createInputView(final int newThemeIndex, final boolean forceRecreate) {
535f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka        if (mCurrentInputView != null && mThemeIndex == newThemeIndex && !forceRecreate)
536f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka            return mCurrentInputView;
537f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka
538f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka        if (mKeyboardView != null) {
539f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka            mKeyboardView.closing();
540f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka        }
541f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka
5425a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka        final int oldThemeIndex = mThemeIndex;
543f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka        Utils.GCUtils.getInstance().reset();
544f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka        boolean tryGC = true;
545f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka        for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
546f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka            try {
5475a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka                setContextThemeWrapper(mInputMethodService, newThemeIndex);
548f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka                mCurrentInputView = (InputView)LayoutInflater.from(mThemeContext).inflate(
54913a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka                        R.layout.input_view, null);
550f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka                tryGC = false;
551f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka            } catch (OutOfMemoryError e) {
552f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka                Log.w(TAG, "load keyboard failed: " + e);
5535a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka                tryGC = Utils.GCUtils.getInstance().tryGCOrWait(
5545a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka                        oldThemeIndex + "," + newThemeIndex, e);
555f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka            } catch (InflateException e) {
556f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka                Log.w(TAG, "load keyboard failed: " + e);
5575a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka                tryGC = Utils.GCUtils.getInstance().tryGCOrWait(
5585a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka                        oldThemeIndex + "," + newThemeIndex, e);
559979f8690967ff5409fe18f5085858ccdb8e0ccf1satok            }
560979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        }
561f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka
562c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka        mKeyboardView = (LatinKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view);
5635a7a696aff6718d4e0250c394a9d01cbf2a16916Tadashi G. Takaoka        mKeyboardView.setKeyboardActionListener(mInputMethodService);
5645ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette
5655ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette        // This always needs to be set since the accessibility state can
5665ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette        // potentially change without the input view being re-created.
5675ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette        AccessibleKeyboardViewProxy.setView(mKeyboardView);
5685ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette
569f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka        return mCurrentInputView;
5708d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka    }
5718d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka
572f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka    private void postSetInputView(final View newInputView) {
573979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        mInputMethodService.mHandler.post(new Runnable() {
5748d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka            @Override
575979f8690967ff5409fe18f5085858ccdb8e0ccf1satok            public void run() {
576f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka                if (newInputView != null) {
577f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka                    mInputMethodService.setInputView(newInputView);
578979f8690967ff5409fe18f5085858ccdb8e0ccf1satok                }
579979f8690967ff5409fe18f5085858ccdb8e0ccf1satok                mInputMethodService.updateInputViewShown();
5808d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka            }
5818d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka        });
582979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    }
583979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
5848d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka    @Override
585979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
586979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        if (PREF_KEYBOARD_LAYOUT.equals(key)) {
5872ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa            final int themeIndex = getKeyboardThemeIndex(mInputMethodService, sharedPreferences);
5882ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa            postSetInputView(createInputView(themeIndex, false));
5892ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa        } else if (Settings.PREF_SHOW_SETTINGS_KEY.equals(key)) {
590f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka            postSetInputView(createInputView(mThemeIndex, true));
591979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        }
592979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    }
593979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
5941b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka    public void onAutoCorrectionStateChanged(boolean isAutoCorrection) {
5955e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka        if (mIsAutoCorrectionActive != isAutoCorrection) {
5961b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka            mIsAutoCorrectionActive = isAutoCorrection;
5975e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka            final LatinKeyboard keyboard = getLatinKeyboard();
5985e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka            if (keyboard != null && keyboard.needsAutoCorrectionSpacebarLed()) {
5995e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka                final Key invalidatedKey = keyboard.onAutoCorrectionStateChanged(isAutoCorrection);
600c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka                final LatinKeyboardView keyboardView = getKeyboardView();
6015e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka                if (keyboardView != null)
6025e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka                    keyboardView.invalidateKey(invalidatedKey);
6035e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka            }
60441feaaadb758a8b31d3e436063b4b5faed104d4dsatok        }
60541feaaadb758a8b31d3e436063b4b5faed104d4dsatok    }
6061508c0e84f0cd93ab6f5d46fea5026e833f299bcKen Wakasa
6072ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa    private static int getF2KeyMode(boolean settingsKeyEnabled, boolean noSettingsKey) {
6082ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa        if (noSettingsKey) {
6092ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa            // Never shows the Settings key
610cd96a691b14b384face577d907f6c1aa33b47233Tadashi G. Takaoka            return KeyboardId.F2KEY_MODE_SHORTCUT_IME;
611cd96a691b14b384face577d907f6c1aa33b47233Tadashi G. Takaoka        }
6122ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa
6132ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa        if (settingsKeyEnabled) {
6142ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa            return KeyboardId.F2KEY_MODE_SETTINGS;
6152ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa        } else {
6162ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa            // It should be alright to fall back to the Settings key on 7-inch layouts
6172ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa            // even when the Settings key is not explicitly enabled.
6182ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa            return KeyboardId.F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS;
6192ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa        }
620cd96a691b14b384face577d907f6c1aa33b47233Tadashi G. Takaoka    }
621923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project}
622