2009-03-13 22:11:42 +00:00
|
|
|
/*
|
2010-03-26 22:07:10 +00:00
|
|
|
* Copyright (C) 2008 The Android Open Source Project
|
2010-12-02 11:54:32 +00:00
|
|
|
*
|
2009-03-13 22:11:42 +00:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
|
|
* use this file except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at
|
2010-12-02 11:54:32 +00:00
|
|
|
*
|
2009-03-13 22:11:42 +00:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2010-12-02 11:54:32 +00:00
|
|
|
*
|
2009-03-13 22:11:42 +00:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
* License for the specific language governing permissions and limitations under
|
|
|
|
* the License.
|
|
|
|
*/
|
|
|
|
|
2010-12-02 11:54:32 +00:00
|
|
|
package com.android.inputmethod.keyboard;
|
2009-03-13 22:11:42 +00:00
|
|
|
|
2011-05-23 09:30:21 +00:00
|
|
|
import android.content.Context;
|
|
|
|
import android.content.SharedPreferences;
|
2011-07-30 00:20:01 +00:00
|
|
|
import android.content.res.Configuration;
|
2011-05-23 09:30:21 +00:00
|
|
|
import android.content.res.Resources;
|
2011-08-22 08:17:42 +00:00
|
|
|
import android.util.DisplayMetrics;
|
2011-05-23 09:30:21 +00:00
|
|
|
import android.util.Log;
|
2011-05-24 12:08:20 +00:00
|
|
|
import android.view.ContextThemeWrapper;
|
2011-05-23 09:30:21 +00:00
|
|
|
import android.view.InflateException;
|
|
|
|
import android.view.LayoutInflater;
|
|
|
|
import android.view.View;
|
|
|
|
import android.view.inputmethod.EditorInfo;
|
|
|
|
|
2011-05-18 00:03:25 +00:00
|
|
|
import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
|
2011-12-05 06:02:06 +00:00
|
|
|
import com.android.inputmethod.keyboard.internal.KeyboardState;
|
2011-09-20 07:16:34 +00:00
|
|
|
import com.android.inputmethod.latin.InputView;
|
2010-12-02 11:54:32 +00:00
|
|
|
import com.android.inputmethod.latin.LatinIME;
|
|
|
|
import com.android.inputmethod.latin.LatinImeLogger;
|
2011-08-26 11:22:47 +00:00
|
|
|
import com.android.inputmethod.latin.LocaleUtils;
|
2010-12-02 11:54:32 +00:00
|
|
|
import com.android.inputmethod.latin.R;
|
2011-01-25 03:13:35 +00:00
|
|
|
import com.android.inputmethod.latin.Settings;
|
2011-12-08 13:10:40 +00:00
|
|
|
import com.android.inputmethod.latin.SettingsValues;
|
2010-12-02 11:54:32 +00:00
|
|
|
import com.android.inputmethod.latin.SubtypeSwitcher;
|
2011-01-25 03:13:35 +00:00
|
|
|
import com.android.inputmethod.latin.Utils;
|
2010-12-02 09:46:21 +00:00
|
|
|
|
2010-09-08 16:41:58 +00:00
|
|
|
import java.lang.ref.SoftReference;
|
2010-09-06 05:50:50 +00:00
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.Locale;
|
|
|
|
|
2011-12-07 10:31:11 +00:00
|
|
|
public class KeyboardSwitcher implements KeyboardState.SwitchActions,
|
|
|
|
SharedPreferences.OnSharedPreferenceChangeListener {
|
2011-05-28 14:47:21 +00:00
|
|
|
private static final String TAG = KeyboardSwitcher.class.getSimpleName();
|
|
|
|
private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG;
|
2009-03-13 22:11:42 +00:00
|
|
|
|
2011-09-16 11:18:46 +00:00
|
|
|
public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20110916";
|
2010-12-28 11:49:58 +00:00
|
|
|
private static final int[] KEYBOARD_THEMES = {
|
2011-05-24 12:08:20 +00:00
|
|
|
R.style.KeyboardTheme,
|
|
|
|
R.style.KeyboardTheme_HighContrast,
|
|
|
|
R.style.KeyboardTheme_Stone,
|
|
|
|
R.style.KeyboardTheme_Stone_Bold,
|
|
|
|
R.style.KeyboardTheme_Gingerbread,
|
2011-06-21 11:10:51 +00:00
|
|
|
R.style.KeyboardTheme_IceCreamSandwich,
|
2010-11-19 08:31:20 +00:00
|
|
|
};
|
2010-08-20 05:35:02 +00:00
|
|
|
|
2010-11-17 07:35:35 +00:00
|
|
|
private SubtypeSwitcher mSubtypeSwitcher;
|
2010-11-26 04:08:36 +00:00
|
|
|
private SharedPreferences mPrefs;
|
2010-11-17 07:35:35 +00:00
|
|
|
|
2011-09-20 07:16:34 +00:00
|
|
|
private InputView mCurrentInputView;
|
2011-08-23 08:57:02 +00:00
|
|
|
private LatinKeyboardView mKeyboardView;
|
2010-11-17 07:35:35 +00:00
|
|
|
private LatinIME mInputMethodService;
|
2011-07-29 23:57:07 +00:00
|
|
|
private String mPackageName;
|
|
|
|
private Resources mResources;
|
2010-09-01 06:45:20 +00:00
|
|
|
|
2011-12-05 06:02:06 +00:00
|
|
|
private KeyboardState mState;
|
2010-11-16 09:47:39 +00:00
|
|
|
|
2011-07-27 00:22:58 +00:00
|
|
|
private KeyboardId mMainKeyboardId;
|
|
|
|
private KeyboardId mSymbolsKeyboardId;
|
|
|
|
private KeyboardId mSymbolsShiftedKeyboardId;
|
2009-04-16 19:56:10 +00:00
|
|
|
|
|
|
|
private KeyboardId mCurrentId;
|
2010-11-11 07:03:19 +00:00
|
|
|
private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache =
|
|
|
|
new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
|
2010-01-16 20:21:23 +00:00
|
|
|
|
2010-12-11 08:06:24 +00:00
|
|
|
/** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of
|
2010-09-02 13:54:37 +00:00
|
|
|
* what user actually typed. */
|
2010-12-11 08:06:24 +00:00
|
|
|
private boolean mIsAutoCorrectionActive;
|
2010-12-17 07:56:15 +00:00
|
|
|
|
2011-06-20 02:58:56 +00:00
|
|
|
private int mThemeIndex = -1;
|
|
|
|
private Context mThemeContext;
|
2010-08-20 05:35:02 +00:00
|
|
|
|
2010-11-17 07:35:35 +00:00
|
|
|
private static final KeyboardSwitcher sInstance = new KeyboardSwitcher();
|
|
|
|
|
|
|
|
public static KeyboardSwitcher getInstance() {
|
|
|
|
return sInstance;
|
|
|
|
}
|
|
|
|
|
|
|
|
private KeyboardSwitcher() {
|
2010-12-10 06:24:28 +00:00
|
|
|
// Intentional empty constructor for singleton.
|
2010-11-17 07:35:35 +00:00
|
|
|
}
|
|
|
|
|
2010-11-26 04:08:36 +00:00
|
|
|
public static void init(LatinIME ims, SharedPreferences prefs) {
|
2011-07-30 00:20:01 +00:00
|
|
|
sInstance.initInternal(ims, prefs);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void initInternal(LatinIME ims, SharedPreferences prefs) {
|
|
|
|
mInputMethodService = ims;
|
|
|
|
mPackageName = ims.getPackageName();
|
|
|
|
mResources = ims.getResources();
|
|
|
|
mPrefs = prefs;
|
|
|
|
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
|
2011-12-07 10:31:11 +00:00
|
|
|
mState = new KeyboardState(this);
|
2011-07-30 00:20:01 +00:00
|
|
|
setContextThemeWrapper(ims, getKeyboardThemeIndex(ims, prefs));
|
|
|
|
prefs.registerOnSharedPreferenceChangeListener(this);
|
2011-06-20 02:58:56 +00:00
|
|
|
}
|
2010-08-20 05:35:02 +00:00
|
|
|
|
2011-06-20 02:58:56 +00:00
|
|
|
private static int getKeyboardThemeIndex(Context context, SharedPreferences prefs) {
|
|
|
|
final String defaultThemeId = context.getString(R.string.config_default_keyboard_theme_id);
|
2011-09-16 11:18:46 +00:00
|
|
|
final String themeId = prefs.getString(PREF_KEYBOARD_LAYOUT, defaultThemeId);
|
2010-12-28 11:49:58 +00:00
|
|
|
try {
|
2011-06-20 02:58:56 +00:00
|
|
|
final int themeIndex = Integer.valueOf(themeId);
|
|
|
|
if (themeIndex >= 0 && themeIndex < KEYBOARD_THEMES.length)
|
|
|
|
return themeIndex;
|
2010-12-28 11:49:58 +00:00
|
|
|
} catch (NumberFormatException e) {
|
2011-06-20 02:58:56 +00:00
|
|
|
// Format error, keyboard theme is default to 0.
|
|
|
|
}
|
|
|
|
Log.w(TAG, "Illegal keyboard theme in preference: " + themeId + ", default to 0");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void setContextThemeWrapper(Context context, int themeIndex) {
|
|
|
|
if (mThemeIndex != themeIndex) {
|
|
|
|
mThemeIndex = themeIndex;
|
|
|
|
mThemeContext = new ContextThemeWrapper(context, KEYBOARD_THEMES[themeIndex]);
|
|
|
|
mKeyboardCache.clear();
|
2010-12-28 11:49:58 +00:00
|
|
|
}
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
|
|
|
|
2011-12-08 13:10:40 +00:00
|
|
|
public void loadKeyboard(EditorInfo editorInfo, SettingsValues settingsValues) {
|
2010-08-20 05:35:02 +00:00
|
|
|
try {
|
2011-07-30 01:19:51 +00:00
|
|
|
mMainKeyboardId = getKeyboardId(editorInfo, false, false, settingsValues);
|
|
|
|
mSymbolsKeyboardId = getKeyboardId(editorInfo, true, false, settingsValues);
|
|
|
|
mSymbolsShiftedKeyboardId = getKeyboardId(editorInfo, true, true, settingsValues);
|
2011-12-08 12:27:57 +00:00
|
|
|
mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols),
|
|
|
|
hasDistinctMultitouch());
|
2010-08-20 05:35:02 +00:00
|
|
|
} catch (RuntimeException e) {
|
2011-07-27 00:22:58 +00:00
|
|
|
Log.w(TAG, "loading keyboard failed: " + mMainKeyboardId, e);
|
|
|
|
LatinImeLogger.logOnException(mMainKeyboardId.toString(), e);
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
2009-04-16 19:56:10 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 08:27:48 +00:00
|
|
|
public void saveKeyboardState() {
|
2011-12-07 03:53:51 +00:00
|
|
|
if (mCurrentId != null) {
|
2011-12-09 07:09:16 +00:00
|
|
|
mState.onSaveKeyboardState();
|
2011-12-07 03:53:51 +00:00
|
|
|
}
|
2011-07-29 17:45:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void onFinishInputView() {
|
|
|
|
mIsAutoCorrectionActive = false;
|
|
|
|
}
|
|
|
|
|
2011-07-27 22:32:25 +00:00
|
|
|
public void onHideWindow() {
|
|
|
|
mIsAutoCorrectionActive = false;
|
|
|
|
}
|
|
|
|
|
2011-07-29 17:45:37 +00:00
|
|
|
private void setKeyboard(final Keyboard keyboard) {
|
2011-05-23 09:30:21 +00:00
|
|
|
final Keyboard oldKeyboard = mKeyboardView.getKeyboard();
|
2011-07-29 17:45:37 +00:00
|
|
|
mKeyboardView.setKeyboard(keyboard);
|
2011-09-20 07:16:34 +00:00
|
|
|
mCurrentInputView.setKeyboardGeometry(keyboard.mTopPadding);
|
2011-07-29 17:45:37 +00:00
|
|
|
mCurrentId = keyboard.mId;
|
|
|
|
updateShiftLockState(keyboard);
|
2011-05-23 09:30:21 +00:00
|
|
|
mKeyboardView.setKeyPreviewPopupEnabled(
|
2011-12-08 13:10:40 +00:00
|
|
|
SettingsValues.isKeyPreviewPopupEnabled(mPrefs, mResources),
|
|
|
|
SettingsValues.getKeyPreviewPopupDismissDelay(mPrefs, mResources));
|
2011-02-20 12:12:51 +00:00
|
|
|
final boolean localeChanged = (oldKeyboard == null)
|
2011-07-29 17:45:37 +00:00
|
|
|
|| !keyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale);
|
2011-02-20 12:12:51 +00:00
|
|
|
mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged);
|
2011-08-15 10:58:23 +00:00
|
|
|
updateShiftState();
|
2009-04-16 19:56:10 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 17:45:37 +00:00
|
|
|
private void updateShiftLockState(Keyboard keyboard) {
|
|
|
|
if (mCurrentId.equals(mSymbolsShiftedKeyboardId)) {
|
|
|
|
// Symbol keyboard may have an ALT key that has a caps lock style indicator (a.k.a.
|
|
|
|
// sticky shift key). To show or dismiss the indicator, we need to call setShiftLocked()
|
|
|
|
// that takes care of the current keyboard having such ALT key or not.
|
|
|
|
keyboard.setShiftLocked(keyboard.hasShiftLockKey());
|
|
|
|
} else if (mCurrentId.equals(mSymbolsKeyboardId)) {
|
|
|
|
// Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the
|
|
|
|
// indicator, we need to call setShiftLocked(false).
|
|
|
|
keyboard.setShiftLocked(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-16 19:56:10 +00:00
|
|
|
private LatinKeyboard getKeyboard(KeyboardId id) {
|
2010-11-11 07:03:19 +00:00
|
|
|
final SoftReference<LatinKeyboard> ref = mKeyboardCache.get(id);
|
2010-09-08 16:41:58 +00:00
|
|
|
LatinKeyboard keyboard = (ref == null) ? null : ref.get();
|
|
|
|
if (keyboard == null) {
|
2011-08-26 11:22:47 +00:00
|
|
|
final Locale savedLocale = LocaleUtils.setSystemLocale(mResources, id.mLocale);
|
2011-07-29 00:05:40 +00:00
|
|
|
try {
|
2011-10-03 09:34:34 +00:00
|
|
|
final LatinKeyboard.Builder builder = new LatinKeyboard.Builder(mThemeContext);
|
|
|
|
builder.load(id);
|
|
|
|
builder.setTouchPositionCorrectionEnabled(
|
|
|
|
mSubtypeSwitcher.currentSubtypeContainsExtraValueKey(
|
|
|
|
LatinIME.SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION));
|
|
|
|
keyboard = builder.build();
|
2011-07-29 00:05:40 +00:00
|
|
|
} finally {
|
2011-08-26 11:22:47 +00:00
|
|
|
LocaleUtils.setSystemLocale(mResources, savedLocale);
|
2011-07-29 00:05:40 +00:00
|
|
|
}
|
2010-11-11 07:03:19 +00:00
|
|
|
mKeyboardCache.put(id, new SoftReference<LatinKeyboard>(keyboard));
|
2011-07-29 00:05:40 +00:00
|
|
|
|
|
|
|
if (DEBUG_CACHE) {
|
2010-11-11 07:03:19 +00:00
|
|
|
Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": "
|
2011-09-28 03:08:48 +00:00
|
|
|
+ ((ref == null) ? "LOAD" : "GCed") + " id=" + id
|
|
|
|
+ " theme=" + Keyboard.themeName(keyboard.mThemeId));
|
2011-07-29 00:05:40 +00:00
|
|
|
}
|
2011-05-17 10:02:32 +00:00
|
|
|
} else if (DEBUG_CACHE) {
|
2011-09-28 03:08:48 +00:00
|
|
|
Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT id=" + id
|
|
|
|
+ " theme=" + Keyboard.themeName(keyboard.mThemeId));
|
2009-04-16 19:56:10 +00:00
|
|
|
}
|
2010-11-11 07:03:19 +00:00
|
|
|
|
2010-12-11 08:06:24 +00:00
|
|
|
keyboard.onAutoCorrectionStateChanged(mIsAutoCorrectionActive);
|
2011-08-03 16:24:13 +00:00
|
|
|
keyboard.setShiftLocked(false);
|
2010-11-11 07:03:19 +00:00
|
|
|
keyboard.setShifted(false);
|
2011-01-12 11:33:54 +00:00
|
|
|
// If the cached keyboard had been switched to another keyboard while the language was
|
|
|
|
// displayed on its spacebar, it might have had arbitrary text fade factor. In such case,
|
2011-01-25 03:13:35 +00:00
|
|
|
// we should reset the text fade factor. It is also applicable to shortcut key.
|
2011-01-12 11:33:54 +00:00
|
|
|
keyboard.setSpacebarTextFadeFactor(0.0f, null);
|
2011-03-03 05:34:11 +00:00
|
|
|
keyboard.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady(), null);
|
2010-09-08 16:41:58 +00:00
|
|
|
return keyboard;
|
2009-04-16 19:56:10 +00:00
|
|
|
}
|
|
|
|
|
2011-07-30 01:19:51 +00:00
|
|
|
private KeyboardId getKeyboardId(EditorInfo editorInfo, final boolean isSymbols,
|
2011-12-08 13:10:40 +00:00
|
|
|
final boolean isShift, SettingsValues settingsValues) {
|
2011-07-30 01:19:51 +00:00
|
|
|
final int mode = Utils.getKeyboardMode(editorInfo);
|
2010-11-22 00:40:38 +00:00
|
|
|
final int xmlId;
|
2011-07-27 00:22:58 +00:00
|
|
|
switch (mode) {
|
|
|
|
case KeyboardId.MODE_PHONE:
|
|
|
|
xmlId = (isSymbols && isShift) ? R.xml.kbd_phone_shift : R.xml.kbd_phone;
|
|
|
|
break;
|
|
|
|
case KeyboardId.MODE_NUMBER:
|
|
|
|
xmlId = R.xml.kbd_number;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (isSymbols) {
|
|
|
|
xmlId = isShift ? R.xml.kbd_symbols_shift : R.xml.kbd_symbols;
|
2010-11-24 01:55:22 +00:00
|
|
|
} else {
|
|
|
|
xmlId = R.xml.kbd_qwerty;
|
|
|
|
}
|
2011-07-27 00:22:58 +00:00
|
|
|
break;
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|
2011-07-27 00:22:58 +00:00
|
|
|
|
2011-08-22 03:19:37 +00:00
|
|
|
final boolean settingsKeyEnabled = settingsValues.isSettingsKeyEnabled();
|
2011-10-04 01:54:23 +00:00
|
|
|
@SuppressWarnings("deprecation")
|
2011-08-01 01:20:20 +00:00
|
|
|
final boolean noMicrophone = Utils.inPrivateImeOptions(
|
|
|
|
mPackageName, LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo)
|
|
|
|
|| Utils.inPrivateImeOptions(
|
|
|
|
null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo);
|
|
|
|
final boolean voiceKeyEnabled = settingsValues.isVoiceKeyEnabled(editorInfo)
|
|
|
|
&& !noMicrophone;
|
2011-07-30 01:19:51 +00:00
|
|
|
final boolean voiceKeyOnMain = settingsValues.isVoiceKeyOnMain();
|
2011-07-29 23:57:07 +00:00
|
|
|
final boolean noSettingsKey = Utils.inPrivateImeOptions(
|
2011-07-30 01:19:51 +00:00
|
|
|
mPackageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, editorInfo);
|
|
|
|
final boolean hasSettingsKey = settingsKeyEnabled && !noSettingsKey;
|
|
|
|
final int f2KeyMode = getF2KeyMode(settingsKeyEnabled, noSettingsKey);
|
2011-08-01 01:34:54 +00:00
|
|
|
final boolean hasShortcutKey = voiceKeyEnabled && (isSymbols != voiceKeyOnMain);
|
2011-08-23 08:27:48 +00:00
|
|
|
final boolean forceAscii = Utils.inPrivateImeOptions(
|
|
|
|
mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, editorInfo);
|
|
|
|
final boolean asciiCapable = mSubtypeSwitcher.currentSubtypeContainsExtraValueKey(
|
|
|
|
LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE);
|
|
|
|
final Locale locale = (forceAscii && !asciiCapable)
|
|
|
|
? Locale.US : mSubtypeSwitcher.getInputLocale();
|
2011-07-30 01:19:51 +00:00
|
|
|
final Configuration conf = mResources.getConfiguration();
|
2011-08-22 08:17:42 +00:00
|
|
|
final DisplayMetrics dm = mResources.getDisplayMetrics();
|
2011-07-29 23:57:07 +00:00
|
|
|
|
2010-12-14 06:31:47 +00:00
|
|
|
return new KeyboardId(
|
2011-08-23 08:27:48 +00:00
|
|
|
mResources.getResourceEntryName(xmlId), xmlId, locale, conf.orientation,
|
|
|
|
dm.widthPixels, mode, editorInfo, hasSettingsKey, f2KeyMode, noSettingsKey,
|
|
|
|
voiceKeyEnabled, hasShortcutKey);
|
2011-02-23 11:31:08 +00:00
|
|
|
}
|
|
|
|
|
2010-09-21 07:55:18 +00:00
|
|
|
public int getKeyboardMode() {
|
2011-02-20 13:04:50 +00:00
|
|
|
return mCurrentId != null ? mCurrentId.mMode : KeyboardId.MODE_TEXT;
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|
2010-11-13 08:01:13 +00:00
|
|
|
|
2010-09-21 07:55:18 +00:00
|
|
|
public boolean isAlphabetMode() {
|
2011-12-09 07:09:16 +00:00
|
|
|
return mState.isAlphabetMode();
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|
|
|
|
|
2010-11-13 08:01:13 +00:00
|
|
|
public boolean isInputViewShown() {
|
2011-06-14 07:28:57 +00:00
|
|
|
return mCurrentInputView != null && mCurrentInputView.isShown();
|
2010-11-13 08:01:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isKeyboardAvailable() {
|
2011-05-23 09:30:21 +00:00
|
|
|
if (mKeyboardView != null)
|
|
|
|
return mKeyboardView.getKeyboard() != null;
|
2010-11-13 08:16:34 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-02-20 12:12:51 +00:00
|
|
|
public LatinKeyboard getLatinKeyboard() {
|
2011-05-23 09:30:21 +00:00
|
|
|
if (mKeyboardView != null) {
|
|
|
|
final Keyboard keyboard = mKeyboardView.getKeyboard();
|
2011-02-20 12:12:51 +00:00
|
|
|
if (keyboard instanceof LatinKeyboard)
|
|
|
|
return (LatinKeyboard)keyboard;
|
|
|
|
}
|
2010-11-13 08:16:34 +00:00
|
|
|
return null;
|
2010-11-13 08:01:13 +00:00
|
|
|
}
|
|
|
|
|
2010-11-13 08:16:34 +00:00
|
|
|
public boolean isShiftedOrShiftLocked() {
|
2011-12-06 02:19:39 +00:00
|
|
|
return mState.isShiftedOrShiftLocked();
|
2010-11-13 08:16:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isManualTemporaryUpperCase() {
|
2011-12-06 02:19:39 +00:00
|
|
|
return mState.isManualTemporaryUpperCase();
|
2010-11-13 08:16:34 +00:00
|
|
|
}
|
|
|
|
|
2011-12-07 10:31:11 +00:00
|
|
|
// Implements {@link KeyboardState.SwitchActions}.
|
|
|
|
@Override
|
|
|
|
public void setShifted(int shiftMode) {
|
2011-12-06 10:14:45 +00:00
|
|
|
mInputMethodService.mHandler.cancelUpdateShiftState();
|
2010-11-13 08:16:34 +00:00
|
|
|
LatinKeyboard latinKeyboard = getLatinKeyboard();
|
2011-12-05 09:16:40 +00:00
|
|
|
if (latinKeyboard == null)
|
|
|
|
return;
|
|
|
|
if (shiftMode == AUTOMATIC_SHIFT) {
|
|
|
|
latinKeyboard.setAutomaticTemporaryUpperCase();
|
|
|
|
} else {
|
|
|
|
final boolean shifted = (shiftMode == MANUAL_SHIFT);
|
2010-11-23 01:20:48 +00:00
|
|
|
// On non-distinct multi touch panel device, we should also turn off the shift locked
|
|
|
|
// state when shift key is pressed to go to normal mode.
|
2011-12-05 09:16:40 +00:00
|
|
|
// On the other hand, on distinct multi touch panel device, turning off the shift
|
|
|
|
// locked state with shift key pressing is handled by onReleaseShift().
|
2011-12-08 12:27:57 +00:00
|
|
|
if (!hasDistinctMultitouch() && !shifted && mState.isShiftLocked()) {
|
2010-11-23 01:20:48 +00:00
|
|
|
latinKeyboard.setShiftLocked(false);
|
|
|
|
}
|
2011-12-06 05:42:30 +00:00
|
|
|
latinKeyboard.setShifted(shifted);
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
2011-12-06 05:42:30 +00:00
|
|
|
mKeyboardView.invalidateAllKeys();
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
|
|
|
|
2011-12-07 10:31:11 +00:00
|
|
|
// Implements {@link KeyboardState.SwitchActions}.
|
|
|
|
@Override
|
|
|
|
public void setShiftLocked(boolean shiftLocked) {
|
2011-12-06 10:14:45 +00:00
|
|
|
mInputMethodService.mHandler.cancelUpdateShiftState();
|
2010-11-13 08:16:34 +00:00
|
|
|
LatinKeyboard latinKeyboard = getLatinKeyboard();
|
2011-12-06 02:19:39 +00:00
|
|
|
if (latinKeyboard == null)
|
|
|
|
return;
|
|
|
|
latinKeyboard.setShiftLocked(shiftLocked);
|
|
|
|
mKeyboardView.invalidateAllKeys();
|
2011-12-06 10:14:45 +00:00
|
|
|
if (!shiftLocked) {
|
|
|
|
// To be able to turn off caps lock by "double tap" on shift key, we should ignore
|
|
|
|
// the second tap of the "double tap" from now for a while because we just have
|
|
|
|
// already turned off caps lock above.
|
|
|
|
mKeyboardView.startIgnoringDoubleTap();
|
|
|
|
}
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
|
|
|
|
2010-11-23 01:20:48 +00:00
|
|
|
/**
|
|
|
|
* Toggle keyboard shift state triggered by user touch event.
|
|
|
|
*/
|
2010-11-13 08:16:34 +00:00
|
|
|
public void toggleShift() {
|
2011-12-09 07:09:16 +00:00
|
|
|
mState.onToggleShift();
|
2010-11-13 08:16:34 +00:00
|
|
|
}
|
|
|
|
|
2011-12-08 07:30:13 +00:00
|
|
|
/**
|
|
|
|
* Toggle caps lock state triggered by user touch event.
|
|
|
|
*/
|
2010-11-13 08:16:34 +00:00
|
|
|
public void toggleCapsLock() {
|
2011-12-09 07:09:16 +00:00
|
|
|
mState.onToggleCapsLock();
|
2010-11-16 09:47:39 +00:00
|
|
|
}
|
|
|
|
|
2011-12-08 07:30:13 +00:00
|
|
|
/**
|
2011-12-08 12:03:25 +00:00
|
|
|
* Toggle between alphabet and symbols modes triggered by user touch event.
|
2011-12-08 07:30:13 +00:00
|
|
|
*/
|
2011-12-08 12:03:25 +00:00
|
|
|
public void toggleAlphabetAndSymbols() {
|
2011-12-09 07:09:16 +00:00
|
|
|
mState.onToggleAlphabetAndSymbols();
|
2011-12-05 07:35:32 +00:00
|
|
|
}
|
|
|
|
|
2010-11-23 01:20:48 +00:00
|
|
|
/**
|
|
|
|
* Update keyboard shift state triggered by connected EditText status change.
|
|
|
|
*/
|
2010-11-13 08:16:34 +00:00
|
|
|
public void updateShiftState() {
|
2011-12-09 07:09:16 +00:00
|
|
|
mState.onUpdateShiftState(mInputMethodService.getCurrentAutoCapsState());
|
2010-11-16 09:47:39 +00:00
|
|
|
}
|
|
|
|
|
2011-03-02 19:43:13 +00:00
|
|
|
public void onPressShift(boolean withSliding) {
|
2011-12-09 07:09:16 +00:00
|
|
|
mState.onPressShift(withSliding);
|
2010-11-13 08:16:34 +00:00
|
|
|
}
|
|
|
|
|
2011-03-02 19:43:13 +00:00
|
|
|
public void onReleaseShift(boolean withSliding) {
|
2011-12-09 07:09:16 +00:00
|
|
|
mState.onReleaseShift(withSliding);
|
2010-11-16 09:47:39 +00:00
|
|
|
}
|
|
|
|
|
2010-11-16 08:28:50 +00:00
|
|
|
public void onPressSymbol() {
|
2011-12-09 07:09:16 +00:00
|
|
|
mState.onPressSymbol();
|
2010-11-16 08:28:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void onReleaseSymbol() {
|
2011-12-09 07:09:16 +00:00
|
|
|
mState.onReleaseSymbol();
|
2010-11-16 08:28:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void onOtherKeyPressed() {
|
2011-12-05 06:02:06 +00:00
|
|
|
mState.onOtherKeyPressed();
|
2010-11-16 08:28:50 +00:00
|
|
|
}
|
|
|
|
|
2010-12-30 08:19:55 +00:00
|
|
|
public void onCancelInput() {
|
2011-12-09 07:09:16 +00:00
|
|
|
mState.onCancelInput(isSinglePointer());
|
2010-12-30 08:19:55 +00:00
|
|
|
}
|
|
|
|
|
2011-12-07 10:31:11 +00:00
|
|
|
// Implements {@link KeyboardState.SwitchActions}.
|
|
|
|
@Override
|
|
|
|
public void setSymbolsKeyboard() {
|
2011-12-06 08:43:01 +00:00
|
|
|
setKeyboard(getKeyboard(mSymbolsKeyboardId));
|
|
|
|
}
|
|
|
|
|
2011-12-07 10:31:11 +00:00
|
|
|
// Implements {@link KeyboardState.SwitchActions}.
|
|
|
|
@Override
|
|
|
|
public void setAlphabetKeyboard() {
|
2011-12-06 08:43:01 +00:00
|
|
|
setKeyboard(getKeyboard(mMainKeyboardId));
|
2011-12-05 07:35:32 +00:00
|
|
|
}
|
|
|
|
|
2011-12-07 10:31:11 +00:00
|
|
|
// Implements {@link KeyboardState.SwitchActions}.
|
|
|
|
@Override
|
|
|
|
public void setSymbolsShiftedKeyboard() {
|
2011-12-06 08:43:01 +00:00
|
|
|
setKeyboard(getKeyboard(mSymbolsShiftedKeyboardId));
|
|
|
|
}
|
|
|
|
|
2011-04-26 05:27:35 +00:00
|
|
|
public boolean isInMomentarySwitchState() {
|
2011-12-07 10:31:11 +00:00
|
|
|
return mState.isInMomentarySwitchState();
|
2010-12-17 07:56:15 +00:00
|
|
|
}
|
|
|
|
|
2010-12-20 07:21:54 +00:00
|
|
|
public boolean isVibrateAndSoundFeedbackRequired() {
|
2011-10-07 02:46:06 +00:00
|
|
|
return mKeyboardView != null && !mKeyboardView.isInSlidingKeyInput();
|
2010-12-20 07:21:54 +00:00
|
|
|
}
|
|
|
|
|
2011-12-05 07:35:32 +00:00
|
|
|
private boolean isSinglePointer() {
|
|
|
|
return mKeyboardView != null && mKeyboardView.getPointerCount() == 1;
|
2009-07-21 22:47:11 +00:00
|
|
|
}
|
|
|
|
|
2010-09-06 05:26:46 +00:00
|
|
|
public boolean hasDistinctMultitouch() {
|
2011-05-23 09:30:21 +00:00
|
|
|
return mKeyboardView != null && mKeyboardView.hasDistinctMultitouch();
|
2010-09-06 05:26:46 +00:00
|
|
|
}
|
|
|
|
|
2009-07-21 22:47:11 +00:00
|
|
|
/**
|
2010-12-17 07:56:15 +00:00
|
|
|
* Updates state machine to figure out when to automatically snap back to the previous mode.
|
2009-07-21 22:47:11 +00:00
|
|
|
*/
|
2011-12-07 10:31:11 +00:00
|
|
|
public void onCodeInput(int code) {
|
2011-12-09 07:09:16 +00:00
|
|
|
mState.onCodeInput(code, isSinglePointer());
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|
2010-08-20 05:35:02 +00:00
|
|
|
|
2011-08-23 08:57:02 +00:00
|
|
|
public LatinKeyboardView getKeyboardView() {
|
2011-05-23 09:30:21 +00:00
|
|
|
return mKeyboardView;
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
|
|
|
|
2011-05-23 09:30:21 +00:00
|
|
|
public View onCreateInputView() {
|
2011-05-24 12:37:33 +00:00
|
|
|
return createInputView(mThemeIndex, true);
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
|
|
|
|
2011-05-24 12:37:33 +00:00
|
|
|
private View createInputView(final int newThemeIndex, final boolean forceRecreate) {
|
|
|
|
if (mCurrentInputView != null && mThemeIndex == newThemeIndex && !forceRecreate)
|
|
|
|
return mCurrentInputView;
|
|
|
|
|
|
|
|
if (mKeyboardView != null) {
|
|
|
|
mKeyboardView.closing();
|
|
|
|
}
|
|
|
|
|
2011-06-20 02:58:56 +00:00
|
|
|
final int oldThemeIndex = mThemeIndex;
|
2011-05-24 12:37:33 +00:00
|
|
|
Utils.GCUtils.getInstance().reset();
|
|
|
|
boolean tryGC = true;
|
|
|
|
for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
|
|
|
|
try {
|
2011-06-20 02:58:56 +00:00
|
|
|
setContextThemeWrapper(mInputMethodService, newThemeIndex);
|
2011-09-20 07:16:34 +00:00
|
|
|
mCurrentInputView = (InputView)LayoutInflater.from(mThemeContext).inflate(
|
2011-05-24 12:08:20 +00:00
|
|
|
R.layout.input_view, null);
|
2011-05-24 12:37:33 +00:00
|
|
|
tryGC = false;
|
|
|
|
} catch (OutOfMemoryError e) {
|
|
|
|
Log.w(TAG, "load keyboard failed: " + e);
|
2011-06-20 02:58:56 +00:00
|
|
|
tryGC = Utils.GCUtils.getInstance().tryGCOrWait(
|
|
|
|
oldThemeIndex + "," + newThemeIndex, e);
|
2011-05-24 12:37:33 +00:00
|
|
|
} catch (InflateException e) {
|
|
|
|
Log.w(TAG, "load keyboard failed: " + e);
|
2011-06-20 02:58:56 +00:00
|
|
|
tryGC = Utils.GCUtils.getInstance().tryGCOrWait(
|
|
|
|
oldThemeIndex + "," + newThemeIndex, e);
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
|
|
|
}
|
2011-05-24 12:37:33 +00:00
|
|
|
|
2011-08-23 08:57:02 +00:00
|
|
|
mKeyboardView = (LatinKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view);
|
2011-07-08 05:31:29 +00:00
|
|
|
mKeyboardView.setKeyboardActionListener(mInputMethodService);
|
2011-05-18 00:03:25 +00:00
|
|
|
|
|
|
|
// This always needs to be set since the accessibility state can
|
|
|
|
// potentially change without the input view being re-created.
|
|
|
|
AccessibleKeyboardViewProxy.setView(mKeyboardView);
|
|
|
|
|
2011-05-24 12:37:33 +00:00
|
|
|
return mCurrentInputView;
|
2010-11-25 01:02:50 +00:00
|
|
|
}
|
|
|
|
|
2011-05-24 12:37:33 +00:00
|
|
|
private void postSetInputView(final View newInputView) {
|
2011-12-09 07:09:16 +00:00
|
|
|
final LatinIME latinIme = mInputMethodService;
|
|
|
|
latinIme.mHandler.post(new Runnable() {
|
2010-11-25 01:02:50 +00:00
|
|
|
@Override
|
2010-08-20 05:35:02 +00:00
|
|
|
public void run() {
|
2011-05-24 12:37:33 +00:00
|
|
|
if (newInputView != null) {
|
2011-12-09 07:09:16 +00:00
|
|
|
latinIme.setInputView(newInputView);
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
2011-12-09 07:09:16 +00:00
|
|
|
latinIme.updateInputViewShown();
|
2010-11-25 01:02:50 +00:00
|
|
|
}
|
|
|
|
});
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
|
|
|
|
2010-11-25 01:02:50 +00:00
|
|
|
@Override
|
2010-08-20 05:35:02 +00:00
|
|
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
|
|
|
if (PREF_KEYBOARD_LAYOUT.equals(key)) {
|
2011-07-30 01:19:51 +00:00
|
|
|
final int themeIndex = getKeyboardThemeIndex(mInputMethodService, sharedPreferences);
|
|
|
|
postSetInputView(createInputView(themeIndex, false));
|
|
|
|
} else if (Settings.PREF_SHOW_SETTINGS_KEY.equals(key)) {
|
2011-05-24 12:37:33 +00:00
|
|
|
postSetInputView(createInputView(mThemeIndex, true));
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-11 08:06:24 +00:00
|
|
|
public void onAutoCorrectionStateChanged(boolean isAutoCorrection) {
|
2011-06-18 04:33:48 +00:00
|
|
|
if (mIsAutoCorrectionActive != isAutoCorrection) {
|
2010-12-11 08:06:24 +00:00
|
|
|
mIsAutoCorrectionActive = isAutoCorrection;
|
2011-06-18 04:33:48 +00:00
|
|
|
final LatinKeyboard keyboard = getLatinKeyboard();
|
|
|
|
if (keyboard != null && keyboard.needsAutoCorrectionSpacebarLed()) {
|
|
|
|
final Key invalidatedKey = keyboard.onAutoCorrectionStateChanged(isAutoCorrection);
|
2011-08-23 08:57:02 +00:00
|
|
|
final LatinKeyboardView keyboardView = getKeyboardView();
|
2011-06-18 04:33:48 +00:00
|
|
|
if (keyboardView != null)
|
|
|
|
keyboardView.invalidateKey(invalidatedKey);
|
|
|
|
}
|
2010-09-02 13:54:37 +00:00
|
|
|
}
|
|
|
|
}
|
2010-09-15 04:37:52 +00:00
|
|
|
|
2011-07-30 01:19:51 +00:00
|
|
|
private static int getF2KeyMode(boolean settingsKeyEnabled, boolean noSettingsKey) {
|
|
|
|
if (noSettingsKey) {
|
|
|
|
// Never shows the Settings key
|
2011-06-23 12:55:56 +00:00
|
|
|
return KeyboardId.F2KEY_MODE_SHORTCUT_IME;
|
|
|
|
}
|
2011-07-30 01:19:51 +00:00
|
|
|
|
|
|
|
if (settingsKeyEnabled) {
|
|
|
|
return KeyboardId.F2KEY_MODE_SETTINGS;
|
|
|
|
} else {
|
|
|
|
// It should be alright to fall back to the Settings key on 7-inch layouts
|
|
|
|
// even when the Settings key is not explicitly enabled.
|
|
|
|
return KeyboardId.F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS;
|
|
|
|
}
|
2011-06-23 12:55:56 +00:00
|
|
|
}
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|