KeyboardSwitcher.java revision 645128af712961456a42cbcc34c0cdf5f0b40a83
1923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/*
2443c360d0afdbab091994244f045f4756feaf2b4Jean-Baptiste Queru * Copyright (C) 2008 The Android Open Source Project
3571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka *
4923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * use this file except in compliance with the License. You may obtain a copy of
6923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License at
7571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka *
8923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0
9571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka *
10923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * License for the specific language governing permissions and limitations under
14923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License.
15923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */
16923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
17571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokapackage com.android.inputmethod.keyboard;
18923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
19c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.content.Context;
20c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.content.SharedPreferences;
21c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.content.res.Resources;
22c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.util.Log;
2313a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaokaimport android.view.ContextThemeWrapper;
24c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.view.InflateException;
25c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.view.LayoutInflater;
26c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.view.View;
27c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaokaimport android.view.inputmethod.EditorInfo;
28c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka
295ac4638f999db4fea8a9e24171dbceb640a10858Alan Viveretteimport com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
30b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyboardState;
31f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaokaimport com.android.inputmethod.latin.InputView;
32571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.LatinIME;
33571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.LatinImeLogger;
34571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.R;
355cd87e1b1c4258e8d016518914eccfbb4437caceTadashi G. Takaokaimport com.android.inputmethod.latin.Settings;
367a16a061e622539e54d7d649dcb8d4965aea575aJean Chalardimport com.android.inputmethod.latin.SettingsValues;
37571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaokaimport com.android.inputmethod.latin.SubtypeSwitcher;
385cd87e1b1c4258e8d016518914eccfbb4437caceTadashi G. Takaokaimport com.android.inputmethod.latin.Utils;
395a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka
40eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaokapublic class KeyboardSwitcher implements KeyboardState.SwitchActions,
41eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka        SharedPreferences.OnSharedPreferenceChangeListener {
42c25e07d21261583d0eeca5aa0fb6e3ffe93dc603Tadashi G. Takaoka    private static final String TAG = KeyboardSwitcher.class.getSimpleName();
43923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
442d9722e46c774d51c834c3a8b11261a2a22e09d3Ken Wakasa    public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20110916";
4505ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka    private static final int[] KEYBOARD_THEMES = {
4613a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka        R.style.KeyboardTheme,
4713a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka        R.style.KeyboardTheme_HighContrast,
4813a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka        R.style.KeyboardTheme_Stone,
4913a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka        R.style.KeyboardTheme_Stone_Bold,
5013a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka        R.style.KeyboardTheme_Gingerbread,
519116bf18f9c83084f9d451e2e709eff32db27d36Tadashi G. Takaoka        R.style.KeyboardTheme_IceCreamSandwich,
5275fde6489039c09056fb5e64d39630ece5ad57cfTadashi G. Takaoka    };
53979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
540ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok    private SubtypeSwitcher mSubtypeSwitcher;
5527d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa    private SharedPreferences mPrefs;
560ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok
57f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka    private InputView mCurrentInputView;
58c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka    private LatinKeyboardView mKeyboardView;
590ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok    private LatinIME mInputMethodService;
600a054dd1075d679385434ecef38a3d88c7551d7aTadashi G. Takaoka    private Resources mResources;
6131adfa78e2edae188edb05e869f9f68798857582satok
62b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka    private KeyboardState mState;
63889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka
64c42f285b35b24af792b71259445eb7e975a50a29Tadashi G. Takaoka    private KeyboardSet mKeyboardSet;
65353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger
661b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka    /** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of
6741feaaadb758a8b31d3e436063b4b5faed104d4dsatok     * what user actually typed. */
681b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka    private boolean mIsAutoCorrectionActive;
699e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka
705a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka    private int mThemeIndex = -1;
715a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka    private Context mThemeContext;
72979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
730ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok    private static final KeyboardSwitcher sInstance = new KeyboardSwitcher();
740ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok
750ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok    public static KeyboardSwitcher getInstance() {
760ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok        return sInstance;
770ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok    }
780ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok
790ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok    private KeyboardSwitcher() {
80e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaoka        // Intentional empty constructor for singleton.
810ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok    }
820ed7191b4d1013a0b9d2fd1f26733dee7364871dsatok
8327d13713bbb291d25a910f97d88a81fdbabddc0eKen Wakasa    public static void init(LatinIME ims, SharedPreferences prefs) {
84364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka        sInstance.initInternal(ims, prefs);
85364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka    }
86364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka
87364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka    private void initInternal(LatinIME ims, SharedPreferences prefs) {
88364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka        mInputMethodService = ims;
89364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka        mResources = ims.getResources();
90364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka        mPrefs = prefs;
91364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka        mSubtypeSwitcher = SubtypeSwitcher.getInstance();
92eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka        mState = new KeyboardState(this);
93364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka        setContextThemeWrapper(ims, getKeyboardThemeIndex(ims, prefs));
94364f1fd1f84cca6c8d396064bfd8bc8fd1efefcbTadashi G. Takaoka        prefs.registerOnSharedPreferenceChangeListener(this);
955a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka    }
96979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
975a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka    private static int getKeyboardThemeIndex(Context context, SharedPreferences prefs) {
985a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka        final String defaultThemeId = context.getString(R.string.config_default_keyboard_theme_id);
992d9722e46c774d51c834c3a8b11261a2a22e09d3Ken Wakasa        final String themeId = prefs.getString(PREF_KEYBOARD_LAYOUT, defaultThemeId);
10005ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka        try {
1015a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka            final int themeIndex = Integer.valueOf(themeId);
1025a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka            if (themeIndex >= 0 && themeIndex < KEYBOARD_THEMES.length)
1035a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka                return themeIndex;
10405ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka        } catch (NumberFormatException e) {
1055a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka            // Format error, keyboard theme is default to 0.
1065a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka        }
1075a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka        Log.w(TAG, "Illegal keyboard theme in preference: " + themeId + ", default to 0");
1085a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka        return 0;
1095a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka    }
1105a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka
1115a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka    private void setContextThemeWrapper(Context context, int themeIndex) {
1125a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka        if (mThemeIndex != themeIndex) {
1135a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka            mThemeIndex = themeIndex;
1145a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka            mThemeContext = new ContextThemeWrapper(context, KEYBOARD_THEMES[themeIndex]);
115645128af712961456a42cbcc34c0cdf5f0b40a83Tadashi G. Takaoka            KeyboardSet.clearKeyboardCache();
11605ddb9a5d2b36f519a4de4b50448e258f40d2c0fTadashi G. Takaoka        }
117979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    }
118979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
1197a16a061e622539e54d7d649dcb8d4965aea575aJean Chalard    public void loadKeyboard(EditorInfo editorInfo, SettingsValues settingsValues) {
120645128af712961456a42cbcc34c0cdf5f0b40a83Tadashi G. Takaoka        mKeyboardSet = new KeyboardSet.Builder(mThemeContext, editorInfo, settingsValues)
121645128af712961456a42cbcc34c0cdf5f0b40a83Tadashi G. Takaoka                .build();
122645128af712961456a42cbcc34c0cdf5f0b40a83Tadashi G. Takaoka        final KeyboardId mainKeyboardId = mKeyboardSet.getMainKeyboardId();
123979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        try {
124805402e8fa90117ecfc6f1446dc5844d828a6bbcTadashi G. Takaoka            mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols),
125805402e8fa90117ecfc6f1446dc5844d828a6bbcTadashi G. Takaoka                    hasDistinctMultitouch());
126979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        } catch (RuntimeException e) {
127645128af712961456a42cbcc34c0cdf5f0b40a83Tadashi G. Takaoka            Log.w(TAG, "loading keyboard failed: " + mainKeyboardId, e);
128645128af712961456a42cbcc34c0cdf5f0b40a83Tadashi G. Takaoka            LatinImeLogger.logOnException(mainKeyboardId.toString(), e);
129645128af712961456a42cbcc34c0cdf5f0b40a83Tadashi G. Takaoka            return;
130645128af712961456a42cbcc34c0cdf5f0b40a83Tadashi G. Takaoka        }
131645128af712961456a42cbcc34c0cdf5f0b40a83Tadashi G. Takaoka        // TODO: Should get rid of this special case handling for Phone Number layouts once we
132645128af712961456a42cbcc34c0cdf5f0b40a83Tadashi G. Takaoka        // have separate layouts with unique KeyboardIds for alphabet and alphabet-shifted
133645128af712961456a42cbcc34c0cdf5f0b40a83Tadashi G. Takaoka        // respectively.
134645128af712961456a42cbcc34c0cdf5f0b40a83Tadashi G. Takaoka        if (mainKeyboardId.isPhoneKeyboard()) {
135645128af712961456a42cbcc34c0cdf5f0b40a83Tadashi G. Takaoka            mState.onToggleAlphabetAndSymbols();
136979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        }
137353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger    }
138353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger
13959f8ca752d5f79d4469519623590052c050c9d23Tadashi G. Takaoka    public void saveKeyboardState() {
140dc52e7c646bafb00898c3f2ebec064a5920e58fcTadashi G. Takaoka        if (isKeyboardAvailable()) {
14110dcc7eb672a561a1d9f510f4d2109dcab251e36Tadashi G. Takaoka            mState.onSaveKeyboardState();
1422e263b70d5769b52cba4a002e44dbf81db5de7f8Tadashi G. Takaoka        }
143055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka    }
144055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka
145055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka    public void onFinishInputView() {
146055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka        mIsAutoCorrectionActive = false;
147055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka    }
148055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka
149c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka    public void onHideWindow() {
150c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka        mIsAutoCorrectionActive = false;
151c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka    }
152c3d175c01ff1956ddb1c2d608d69af1793b4ad8aTadashi G. Takaoka
153055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka    private void setKeyboard(final Keyboard keyboard) {
154c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka        final Keyboard oldKeyboard = mKeyboardView.getKeyboard();
155055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka        mKeyboardView.setKeyboard(keyboard);
156f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka        mCurrentInputView.setKeyboardGeometry(keyboard.mTopPadding);
157c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka        mKeyboardView.setKeyPreviewPopupEnabled(
1587a16a061e622539e54d7d649dcb8d4965aea575aJean Chalard                SettingsValues.isKeyPreviewPopupEnabled(mPrefs, mResources),
1597a16a061e622539e54d7d649dcb8d4965aea575aJean Chalard                SettingsValues.getKeyPreviewPopupDismissDelay(mPrefs, mResources));
160050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka        final boolean localeChanged = (oldKeyboard == null)
161055054eef3ccd32c6dfd69a3f76bfb7383ea93bbTadashi G. Takaoka                || !keyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale);
16223d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka        if (keyboard instanceof LatinKeyboard) {
16323d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka            final LatinKeyboard latinKeyboard = (LatinKeyboard)keyboard;
16423d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka            latinKeyboard.updateAutoCorrectionState(mIsAutoCorrectionActive);
16523d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka            // If the cached keyboard had been switched to another keyboard while the language was
16623d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka            // displayed on its spacebar, it might have had arbitrary text fade factor. In such
16723d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka            // case, we should reset the text fade factor. It is also applicable to shortcut key.
16823d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka            latinKeyboard.updateSpacebarLanguage(0.0f,
16923d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka                    Utils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */),
17023d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka                    mSubtypeSwitcher.needsToDisplayLanguage(latinKeyboard.mId.mLocale));
17123d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka            latinKeyboard.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady());
17223d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka        }
173286a5bf1c68c8dd06ece9701a904593af2457586Ken Wakasa        updateShiftState();
17423d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka        mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged);
175353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger    }
176353da6d207bed3d32ec38b9ce52e4a136adbf060Brandon Ballinger
1773a2896c80475094f751ef447fc9c97028bfc2265Tadashi G. Takaoka    public boolean isAlphabetMode() {
178df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka        final Keyboard keyboard = getLatinKeyboard();
179df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka        return keyboard != null && keyboard.mId.isAlphabetKeyboard();
180923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
181923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1821679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka    public boolean isInputViewShown() {
18386e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka        return mCurrentInputView != null && mCurrentInputView.isShown();
1841679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka    }
1851679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka
186df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka    public boolean isShiftedOrShiftLocked() {
187df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka        final Keyboard keyboard = getLatinKeyboard();
188df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka        return keyboard != null && keyboard.isShiftedOrShiftLocked();
189df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka    }
190df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka
191df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka    public boolean isManualTemporaryUpperCase() {
192df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka        final Keyboard keyboard = getLatinKeyboard();
193df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka        return keyboard != null && keyboard.isManualTemporaryUpperCase();
194df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka    }
195df9deffba241d3f1527092212de02f5c77a0b24aTadashi G. Takaoka
1961679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka    public boolean isKeyboardAvailable() {
197c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka        if (mKeyboardView != null)
198c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka            return mKeyboardView.getKeyboard() != null;
199b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka        return false;
200b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka    }
201b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka
202050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka    public LatinKeyboard getLatinKeyboard() {
203c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka        if (mKeyboardView != null) {
204c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka            final Keyboard keyboard = mKeyboardView.getKeyboard();
205050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka            if (keyboard instanceof LatinKeyboard)
206050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka                return (LatinKeyboard)keyboard;
207050c0462dc2ada5a5afecec5b6745693c5066b85Tadashi G. Takaoka        }
208b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka        return null;
2091679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka    }
2101679432d1c8a8cfe6ff09be0a49792f4af91ab35Tadashi G. Takaoka
211eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    // Implements {@link KeyboardState.SwitchActions}.
212eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    @Override
213eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    public void setShifted(int shiftMode) {
214f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka        mInputMethodService.mHandler.cancelUpdateShiftState();
215b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka        LatinKeyboard latinKeyboard = getLatinKeyboard();
2166ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka        if (latinKeyboard == null)
2176ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka            return;
2186ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka        if (shiftMode == AUTOMATIC_SHIFT) {
2196ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka            latinKeyboard.setAutomaticTemporaryUpperCase();
2206ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka        } else {
2216ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka            final boolean shifted = (shiftMode == MANUAL_SHIFT);
2220d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka            // On non-distinct multi touch panel device, we should also turn off the shift locked
2230d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka            // state when shift key is pressed to go to normal mode.
2246ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka            // On the other hand, on distinct multi touch panel device, turning off the shift
2256ddb07433fc8ed8675f0996a48790a05a97b61f0Tadashi G. Takaoka            // locked state with shift key pressing is handled by onReleaseShift().
226805402e8fa90117ecfc6f1446dc5844d828a6bbcTadashi G. Takaoka            if (!hasDistinctMultitouch() && !shifted && mState.isShiftLocked()) {
2270d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka                latinKeyboard.setShiftLocked(false);
2280d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka            }
2294f7f61730cbd45871c1e9044da84b494831f97c3Tadashi G. Takaoka            latinKeyboard.setShifted(shifted);
230979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        }
2314f7f61730cbd45871c1e9044da84b494831f97c3Tadashi G. Takaoka        mKeyboardView.invalidateAllKeys();
232979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    }
233979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
234eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    // Implements {@link KeyboardState.SwitchActions}.
235eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    @Override
236eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    public void setShiftLocked(boolean shiftLocked) {
237f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka        mInputMethodService.mHandler.cancelUpdateShiftState();
238b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka        LatinKeyboard latinKeyboard = getLatinKeyboard();
239c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka        if (latinKeyboard == null)
240c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka            return;
241c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka        latinKeyboard.setShiftLocked(shiftLocked);
242c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka        mKeyboardView.invalidateAllKeys();
243f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka        if (!shiftLocked) {
244f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka            // To be able to turn off caps lock by "double tap" on shift key, we should ignore
245f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka            // the second tap of the "double tap" from now for a while because we just have
246f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka            // already turned off caps lock above.
247f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka            mKeyboardView.startIgnoringDoubleTap();
248f47993ee34d1111fdbb1afb44fcac64a132a2e57Tadashi G. Takaoka        }
249979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    }
250979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
2510d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka    /**
2520d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka     * Toggle keyboard shift state triggered by user touch event.
2530d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka     */
254b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka    public void toggleShift() {
25510dcc7eb672a561a1d9f510f4d2109dcab251e36Tadashi G. Takaoka        mState.onToggleShift();
256b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka    }
257b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka
2586ad9b012d947458155609e418aaeb3904cf27f6fTadashi G. Takaoka    /**
2596ad9b012d947458155609e418aaeb3904cf27f6fTadashi G. Takaoka     * Toggle caps lock state triggered by user touch event.
2606ad9b012d947458155609e418aaeb3904cf27f6fTadashi G. Takaoka     */
261b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka    public void toggleCapsLock() {
26210dcc7eb672a561a1d9f510f4d2109dcab251e36Tadashi G. Takaoka        mState.onToggleCapsLock();
263889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka    }
264889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka
2656ad9b012d947458155609e418aaeb3904cf27f6fTadashi G. Takaoka    /**
26696c56cb577ff6b76e2c182f45402842e828c3644Tadashi G. Takaoka     * Toggle between alphabet and symbols modes triggered by user touch event.
2676ad9b012d947458155609e418aaeb3904cf27f6fTadashi G. Takaoka     */
26896c56cb577ff6b76e2c182f45402842e828c3644Tadashi G. Takaoka    public void toggleAlphabetAndSymbols() {
26910dcc7eb672a561a1d9f510f4d2109dcab251e36Tadashi G. Takaoka        mState.onToggleAlphabetAndSymbols();
27046831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka    }
27146831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka
2720d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka    /**
2730d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka     * Update keyboard shift state triggered by connected EditText status change.
2740d0a46da0393c6dd73cccf5e22cb0dd70c99e15aTadashi G. Takaoka     */
275b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka    public void updateShiftState() {
27610dcc7eb672a561a1d9f510f4d2109dcab251e36Tadashi G. Takaoka        mState.onUpdateShiftState(mInputMethodService.getCurrentAutoCapsState());
277889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka    }
278889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka
279e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka    public void onPressShift(boolean withSliding) {
28010dcc7eb672a561a1d9f510f4d2109dcab251e36Tadashi G. Takaoka        mState.onPressShift(withSliding);
281b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka    }
282b643dab73ab9527cc63d896cad81c0cdc92fe5f6Tadashi G. Takaoka
283e59491460b0411bed430a5ca6eca0c56c5bf18d9Tadashi G. Takaoka    public void onReleaseShift(boolean withSliding) {
28410dcc7eb672a561a1d9f510f4d2109dcab251e36Tadashi G. Takaoka        mState.onReleaseShift(withSliding);
285889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka    }
286889691eca1ad991a85fb721deb37ecba6a913762Tadashi G. Takaoka
2876c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka    public void onPressSymbol() {
28810dcc7eb672a561a1d9f510f4d2109dcab251e36Tadashi G. Takaoka        mState.onPressSymbol();
2896c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka    }
2906c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka
2916c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka    public void onReleaseSymbol() {
29210dcc7eb672a561a1d9f510f4d2109dcab251e36Tadashi G. Takaoka        mState.onReleaseSymbol();
2936c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka    }
2946c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka
2956c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka    public void onOtherKeyPressed() {
296b88c9acd88348c160e3d114593660bfd362bee29Tadashi G. Takaoka        mState.onOtherKeyPressed();
2976c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka    }
2986c92ee127df50509d364a2b6d428b223d2cbaa6eTadashi G. Takaoka
2995f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka    public void onCancelInput() {
30010dcc7eb672a561a1d9f510f4d2109dcab251e36Tadashi G. Takaoka        mState.onCancelInput(isSinglePointer());
3015f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka    }
3025f922caff80d5067c5af2bbbae2731ef25c9572aTadashi G. Takaoka
303eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    // Implements {@link KeyboardState.SwitchActions}.
304eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    @Override
305eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    public void setSymbolsKeyboard() {
306645128af712961456a42cbcc34c0cdf5f0b40a83Tadashi G. Takaoka        setKeyboard(mKeyboardSet.getMainKeyboard());
3078a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka    }
3088a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka
309eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    // Implements {@link KeyboardState.SwitchActions}.
310eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    @Override
311eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    public void setAlphabetKeyboard() {
312645128af712961456a42cbcc34c0cdf5f0b40a83Tadashi G. Takaoka        setKeyboard(mKeyboardSet.getSymbolsKeyboard());
31346831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka    }
31446831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka
315eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    // Implements {@link KeyboardState.SwitchActions}.
316eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    @Override
317eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    public void setSymbolsShiftedKeyboard() {
318645128af712961456a42cbcc34c0cdf5f0b40a83Tadashi G. Takaoka        setKeyboard(mKeyboardSet.getSymbolsShiftedKeyboard());
3198a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka    }
3208a70e70c849cc2c5553c6fd79891c22893fd761bTadashi G. Takaoka
321717cef79ead5d63a01d09b47caab0a3d719c69dfTadashi G. Takaoka    public boolean isInMomentarySwitchState() {
322eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka        return mState.isInMomentarySwitchState();
3239e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka    }
3249e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka
325cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka    public boolean isVibrateAndSoundFeedbackRequired() {
326416ee19d330f08e329cce4fd7cb66003cfb64f4aTadashi G. Takaoka        return mKeyboardView != null && !mKeyboardView.isInSlidingKeyInput();
327cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka    }
328cb2469ae17e0ca8a94767008fef3945cb2a3b406Tadashi G. Takaoka
32946831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka    private boolean isSinglePointer() {
33046831d5a4b135e5c21f2212d1d8aef09806800edTadashi G. Takaoka        return mKeyboardView != null && mKeyboardView.getPointerCount() == 1;
331b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani    }
332b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani
333c8b9afe0378e3f33c3f83271bd1df9678a70c2a2Tadashi G. Takaoka    public boolean hasDistinctMultitouch() {
334c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka        return mKeyboardView != null && mKeyboardView.hasDistinctMultitouch();
335c8b9afe0378e3f33c3f83271bd1df9678a70c2a2Tadashi G. Takaoka    }
336c8b9afe0378e3f33c3f83271bd1df9678a70c2a2Tadashi G. Takaoka
337b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani    /**
3389e91472285a1b903631f1e3c998f5aa1efd3e98eTadashi G. Takaoka     * Updates state machine to figure out when to automatically snap back to the previous mode.
339b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani     */
340eef6238f94b5046054d9ae9c06f775362893c0eeTadashi G. Takaoka    public void onCodeInput(int code) {
34110dcc7eb672a561a1d9f510f4d2109dcab251e36Tadashi G. Takaoka        mState.onCodeInput(code, isSinglePointer());
342923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
343979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
344c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka    public LatinKeyboardView getKeyboardView() {
345c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka        return mKeyboardView;
346979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    }
347979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
348c150acc7c85ff2f5eeb5bd2c6ff288df4e46a355Tadashi G. Takaoka    public View onCreateInputView() {
349f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka        return createInputView(mThemeIndex, true);
350979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    }
351979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
352f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka    private View createInputView(final int newThemeIndex, final boolean forceRecreate) {
353f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka        if (mCurrentInputView != null && mThemeIndex == newThemeIndex && !forceRecreate)
354f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka            return mCurrentInputView;
355f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka
356f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka        if (mKeyboardView != null) {
357f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka            mKeyboardView.closing();
358f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka        }
359f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka
3605a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka        final int oldThemeIndex = mThemeIndex;
361f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka        Utils.GCUtils.getInstance().reset();
362f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka        boolean tryGC = true;
363f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka        for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
364f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka            try {
3655a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka                setContextThemeWrapper(mInputMethodService, newThemeIndex);
366f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka                mCurrentInputView = (InputView)LayoutInflater.from(mThemeContext).inflate(
36713a741999480343ccebd81ff6349b572bde17b07Tadashi G. Takaoka                        R.layout.input_view, null);
368f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka                tryGC = false;
369f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka            } catch (OutOfMemoryError e) {
370f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka                Log.w(TAG, "load keyboard failed: " + e);
3715a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka                tryGC = Utils.GCUtils.getInstance().tryGCOrWait(
3725a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka                        oldThemeIndex + "," + newThemeIndex, e);
373f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka            } catch (InflateException e) {
374f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka                Log.w(TAG, "load keyboard failed: " + e);
3755a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka                tryGC = Utils.GCUtils.getInstance().tryGCOrWait(
3765a2d0630474d6df639e97ff48f5f48b220ca4ee9Tadashi G. Takaoka                        oldThemeIndex + "," + newThemeIndex, e);
377979f8690967ff5409fe18f5085858ccdb8e0ccf1satok            }
378979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        }
379f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka
380c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka        mKeyboardView = (LatinKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view);
3815a7a696aff6718d4e0250c394a9d01cbf2a16916Tadashi G. Takaoka        mKeyboardView.setKeyboardActionListener(mInputMethodService);
3825ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette
3835ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette        // This always needs to be set since the accessibility state can
3845ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette        // potentially change without the input view being re-created.
3855ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette        AccessibleKeyboardViewProxy.setView(mKeyboardView);
3865ac4638f999db4fea8a9e24171dbceb640a10858Alan Viverette
387f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka        return mCurrentInputView;
3888d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka    }
3898d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka
390f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka    private void postSetInputView(final View newInputView) {
39110dcc7eb672a561a1d9f510f4d2109dcab251e36Tadashi G. Takaoka        final LatinIME latinIme = mInputMethodService;
39210dcc7eb672a561a1d9f510f4d2109dcab251e36Tadashi G. Takaoka        latinIme.mHandler.post(new Runnable() {
3938d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka            @Override
394979f8690967ff5409fe18f5085858ccdb8e0ccf1satok            public void run() {
395f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka                if (newInputView != null) {
39610dcc7eb672a561a1d9f510f4d2109dcab251e36Tadashi G. Takaoka                    latinIme.setInputView(newInputView);
397979f8690967ff5409fe18f5085858ccdb8e0ccf1satok                }
39810dcc7eb672a561a1d9f510f4d2109dcab251e36Tadashi G. Takaoka                latinIme.updateInputViewShown();
3998d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka            }
4008d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka        });
401979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    }
402979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
4038d7ecc70a6572c288064e41235e4ae8ad5b1b47eTadashi G. Takaoka    @Override
404979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
405979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        if (PREF_KEYBOARD_LAYOUT.equals(key)) {
4062ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa            final int themeIndex = getKeyboardThemeIndex(mInputMethodService, sharedPreferences);
4072ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa            postSetInputView(createInputView(themeIndex, false));
4082ba975afb9529a6574148596db190b939fbc3b3fKen Wakasa        } else if (Settings.PREF_SHOW_SETTINGS_KEY.equals(key)) {
409f3cd2bb33d1688fd6de01787140a1ef2de4b7723Tadashi G. Takaoka            postSetInputView(createInputView(mThemeIndex, true));
410979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        }
411979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    }
412979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
41323d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka    public void onNetworkStateChanged() {
41423d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka        final LatinKeyboard keyboard = getLatinKeyboard();
41523d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka        if (keyboard == null) return;
41623d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka        final Key updatedKey = keyboard.updateShortcutKey(
41723d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka                SubtypeSwitcher.getInstance().isShortcutImeReady());
41823d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka        if (updatedKey != null && mKeyboardView != null) {
41923d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka            mKeyboardView.invalidateKey(updatedKey);
42023d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka        }
42123d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka    }
42223d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka
4231b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka    public void onAutoCorrectionStateChanged(boolean isAutoCorrection) {
4245e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka        if (mIsAutoCorrectionActive != isAutoCorrection) {
4251b1f7f907f6c7d6e849c88ca06c3608bc84d7c5fTadashi G. Takaoka            mIsAutoCorrectionActive = isAutoCorrection;
4265e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka            final LatinKeyboard keyboard = getLatinKeyboard();
4275e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka            if (keyboard != null && keyboard.needsAutoCorrectionSpacebarLed()) {
42823d27fefcbfe04df8f8762d5d50117a58fb011e9Tadashi G. Takaoka                final Key invalidatedKey = keyboard.updateAutoCorrectionState(isAutoCorrection);
429c84bc3460d2fb386a1db2a2c8b135b746fa706cdTadashi G. Takaoka                final LatinKeyboardView keyboardView = getKeyboardView();
4305e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka                if (keyboardView != null)
4315e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka                    keyboardView.invalidateKey(invalidatedKey);
4325e4e05afd2825bf7acb594fef5e7bd21c751dd63Tadashi G. Takaoka            }
43341feaaadb758a8b31d3e436063b4b5faed104d4dsatok        }
43441feaaadb758a8b31d3e436063b4b5faed104d4dsatok    }
4357a91deb685af73aaed09e1b0d6a3027e1b569acaTadashi G. Takaoka
4367a91deb685af73aaed09e1b0d6a3027e1b569acaTadashi G. Takaoka    private static String themeName(int themeId) {
4377a91deb685af73aaed09e1b0d6a3027e1b569acaTadashi G. Takaoka        // This should be aligned with theme-*.xml resource files' themeId attribute.
4387a91deb685af73aaed09e1b0d6a3027e1b569acaTadashi G. Takaoka        switch (themeId) {
4397a91deb685af73aaed09e1b0d6a3027e1b569acaTadashi G. Takaoka        case 0: return "Basic";
4407a91deb685af73aaed09e1b0d6a3027e1b569acaTadashi G. Takaoka        case 1: return "BasicHighContrast";
4417a91deb685af73aaed09e1b0d6a3027e1b569acaTadashi G. Takaoka        case 5: return "IceCreamSandwich";
4427a91deb685af73aaed09e1b0d6a3027e1b569acaTadashi G. Takaoka        case 6: return "Stone";
4437a91deb685af73aaed09e1b0d6a3027e1b569acaTadashi G. Takaoka        case 7: return "StoneBold";
4447a91deb685af73aaed09e1b0d6a3027e1b569acaTadashi G. Takaoka        case 8: return "GingerBread";
4457a91deb685af73aaed09e1b0d6a3027e1b569acaTadashi G. Takaoka        default: return null;
4467a91deb685af73aaed09e1b0d6a3027e1b569acaTadashi G. Takaoka        }
4477a91deb685af73aaed09e1b0d6a3027e1b569acaTadashi G. Takaoka    }
448923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project}
449