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-03-18 05:49:06 +00:00
|
|
|
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
|
2010-12-02 11:54:32 +00:00
|
|
|
import com.android.inputmethod.latin.LatinIME;
|
|
|
|
import com.android.inputmethod.latin.LatinImeLogger;
|
|
|
|
import com.android.inputmethod.latin.R;
|
2011-01-25 03:13:35 +00:00
|
|
|
import com.android.inputmethod.latin.Settings;
|
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-11-11 07:03:19 +00:00
|
|
|
import android.content.Context;
|
2010-08-20 05:35:02 +00:00
|
|
|
import android.content.SharedPreferences;
|
2009-10-12 20:48:35 +00:00
|
|
|
import android.content.res.Resources;
|
2010-11-11 07:03:19 +00:00
|
|
|
import android.util.Log;
|
2010-08-20 05:35:02 +00:00
|
|
|
import android.view.InflateException;
|
2011-02-20 03:54:14 +00:00
|
|
|
import android.view.inputmethod.EditorInfo;
|
2009-10-12 20:48:35 +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;
|
|
|
|
|
2010-08-20 05:35:02 +00:00
|
|
|
public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener {
|
2010-11-11 07:03:19 +00:00
|
|
|
private static final String TAG = "KeyboardSwitcher";
|
|
|
|
private static final boolean DEBUG = false;
|
2010-11-13 08:16:34 +00:00
|
|
|
public static final boolean DEBUG_STATE = false;
|
2009-03-13 22:11:42 +00:00
|
|
|
|
2010-12-28 11:49:58 +00:00
|
|
|
private static String sConfigDefaultKeyboardThemeId;
|
2010-09-02 04:48:48 +00:00
|
|
|
public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902";
|
2010-12-28 11:49:58 +00:00
|
|
|
private static final int[] KEYBOARD_THEMES = {
|
2010-11-19 08:31:20 +00:00
|
|
|
R.layout.input_basic,
|
|
|
|
R.layout.input_basic_highcontrast,
|
|
|
|
R.layout.input_stone_normal,
|
|
|
|
R.layout.input_stone_bold,
|
|
|
|
R.layout.input_gingerbread,
|
2010-12-28 11:49:58 +00:00
|
|
|
R.layout.input_honeycomb,
|
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
|
|
|
|
2010-09-21 07:55:18 +00:00
|
|
|
private LatinKeyboardView mInputView;
|
2010-11-17 07:35:35 +00:00
|
|
|
private LatinIME mInputMethodService;
|
2010-09-01 06:45:20 +00:00
|
|
|
|
2011-04-26 05:27:35 +00:00
|
|
|
// TODO: Combine these key state objects with auto mode switch state.
|
2010-11-13 08:16:34 +00:00
|
|
|
private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift");
|
|
|
|
private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol");
|
2010-11-16 09:47:39 +00:00
|
|
|
|
2009-04-16 19:56:10 +00:00
|
|
|
private KeyboardId mSymbolsId;
|
|
|
|
private KeyboardId mSymbolsShiftedId;
|
|
|
|
|
|
|
|
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
|
|
|
|
2011-02-20 03:54:14 +00:00
|
|
|
private EditorInfo mAttribute;
|
2009-04-16 19:56:10 +00:00
|
|
|
private boolean mIsSymbols;
|
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-11-20 02:45:30 +00:00
|
|
|
private boolean mVoiceKeyEnabled;
|
2010-11-11 00:10:10 +00:00
|
|
|
private boolean mVoiceButtonOnPrimary;
|
2010-12-17 07:56:15 +00:00
|
|
|
|
2011-04-26 05:27:35 +00:00
|
|
|
// TODO: Encapsulate these state handling to separate class and combine with ShiftKeyState
|
|
|
|
// and ModifierKeyState.
|
|
|
|
private static final int SWITCH_STATE_ALPHA = 0;
|
|
|
|
private static final int SWITCH_STATE_SYMBOL_BEGIN = 1;
|
|
|
|
private static final int SWITCH_STATE_SYMBOL = 2;
|
2010-12-17 07:56:15 +00:00
|
|
|
// The following states are used only on the distinct multi-touch panel devices.
|
2011-04-26 05:27:35 +00:00
|
|
|
private static final int SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL = 3;
|
|
|
|
private static final int SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE = 4;
|
|
|
|
private static final int SWITCH_STATE_CHORDING_ALPHA = 5;
|
|
|
|
private static final int SWITCH_STATE_CHORDING_SYMBOL = 6;
|
|
|
|
private int mSwitchState = SWITCH_STATE_ALPHA;
|
2009-03-13 22:11:42 +00:00
|
|
|
|
2011-02-23 11:31:08 +00:00
|
|
|
// Indicates whether or not we have the settings key in option of settings
|
|
|
|
private boolean mSettingsKeyEnabledInSettings;
|
2010-09-15 04:37:52 +00:00
|
|
|
private static final int SETTINGS_KEY_MODE_AUTO = R.string.settings_key_mode_auto;
|
2010-10-22 05:28:12 +00:00
|
|
|
private static final int SETTINGS_KEY_MODE_ALWAYS_SHOW =
|
|
|
|
R.string.settings_key_mode_always_show;
|
2010-11-02 09:55:20 +00:00
|
|
|
// NOTE: No need to have SETTINGS_KEY_MODE_ALWAYS_HIDE here because it's not being referred to
|
|
|
|
// in the source code now.
|
|
|
|
// Default is SETTINGS_KEY_MODE_AUTO.
|
|
|
|
private static final int DEFAULT_SETTINGS_KEY_MODE = SETTINGS_KEY_MODE_AUTO;
|
2010-09-15 04:37:52 +00:00
|
|
|
|
2010-08-20 05:35:02 +00:00
|
|
|
private int mLayoutId;
|
|
|
|
|
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) {
|
2010-11-17 07:35:35 +00:00
|
|
|
sInstance.mInputMethodService = ims;
|
2010-11-26 04:08:36 +00:00
|
|
|
sInstance.mPrefs = prefs;
|
2010-11-17 07:35:35 +00:00
|
|
|
sInstance.mSubtypeSwitcher = SubtypeSwitcher.getInstance();
|
2010-08-20 05:35:02 +00:00
|
|
|
|
2010-12-28 11:49:58 +00:00
|
|
|
try {
|
|
|
|
sConfigDefaultKeyboardThemeId = ims.getString(
|
|
|
|
R.string.config_default_keyboard_theme_id);
|
|
|
|
sInstance.mLayoutId = Integer.valueOf(
|
|
|
|
prefs.getString(PREF_KEYBOARD_LAYOUT, sConfigDefaultKeyboardThemeId));
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
sConfigDefaultKeyboardThemeId = "0";
|
|
|
|
sInstance.mLayoutId = 0;
|
|
|
|
}
|
2010-11-17 07:35:35 +00:00
|
|
|
prefs.registerOnSharedPreferenceChangeListener(sInstance);
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
|
|
|
|
2011-02-20 13:04:50 +00:00
|
|
|
public void loadKeyboard(EditorInfo attribute, boolean voiceKeyEnabled,
|
2010-11-11 00:10:10 +00:00
|
|
|
boolean voiceButtonOnPrimary) {
|
2011-04-26 05:27:35 +00:00
|
|
|
mSwitchState = SWITCH_STATE_ALPHA;
|
2010-08-20 05:35:02 +00:00
|
|
|
try {
|
2011-02-20 13:04:50 +00:00
|
|
|
loadKeyboardInternal(attribute, voiceKeyEnabled, voiceButtonOnPrimary, false);
|
2010-08-20 05:35:02 +00:00
|
|
|
} catch (RuntimeException e) {
|
2011-02-20 03:54:14 +00:00
|
|
|
// Get KeyboardId to record which keyboard has been failed to load.
|
2011-02-20 13:04:50 +00:00
|
|
|
final KeyboardId id = getKeyboardId(attribute, false);
|
2011-02-20 03:54:14 +00:00
|
|
|
Log.w(TAG, "loading keyboard failed: " + id, e);
|
|
|
|
LatinImeLogger.logOnException(id.toString(), e);
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
2009-04-16 19:56:10 +00:00
|
|
|
}
|
|
|
|
|
2011-02-20 13:04:50 +00:00
|
|
|
private void loadKeyboardInternal(EditorInfo attribute, boolean voiceButtonEnabled,
|
2010-11-11 00:10:10 +00:00
|
|
|
boolean voiceButtonOnPrimary, boolean isSymbols) {
|
2010-02-24 03:01:43 +00:00
|
|
|
if (mInputView == null) return;
|
2010-11-11 07:03:19 +00:00
|
|
|
|
2011-02-20 03:54:14 +00:00
|
|
|
mAttribute = attribute;
|
2010-11-20 02:45:30 +00:00
|
|
|
mVoiceKeyEnabled = voiceButtonEnabled;
|
2010-11-11 07:03:19 +00:00
|
|
|
mVoiceButtonOnPrimary = voiceButtonOnPrimary;
|
2009-04-28 18:38:42 +00:00
|
|
|
mIsSymbols = isSymbols;
|
2010-11-11 07:03:19 +00:00
|
|
|
// Update the settings key state because number of enabled IMEs could have been changed
|
2011-02-23 11:31:08 +00:00
|
|
|
mSettingsKeyEnabledInSettings = getSettingsKeyMode(mPrefs, mInputMethodService);
|
2011-02-20 13:04:50 +00:00
|
|
|
final KeyboardId id = getKeyboardId(attribute, isSymbols);
|
2011-02-23 11:31:08 +00:00
|
|
|
makeSymbolsKeyboardIds(id.mMode, attribute);
|
2009-04-16 19:56:10 +00:00
|
|
|
mCurrentId = id;
|
2011-04-19 06:18:20 +00:00
|
|
|
mInputView.setKeyPreviewEnabled(mInputMethodService.getPopupOn());
|
2011-02-20 12:12:51 +00:00
|
|
|
setKeyboard(getKeyboard(id));
|
|
|
|
}
|
|
|
|
|
|
|
|
private void setKeyboard(final Keyboard newKeyboard) {
|
|
|
|
final Keyboard oldKeyboard = mInputView.getKeyboard();
|
|
|
|
mInputView.setKeyboard(newKeyboard);
|
|
|
|
final boolean localeChanged = (oldKeyboard == null)
|
|
|
|
|| !newKeyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale);
|
|
|
|
mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged);
|
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-04-27 06:43:03 +00:00
|
|
|
final Resources res = mInputMethodService.getResources();
|
|
|
|
final Locale savedLocale = Utils.setSystemLocale(res,
|
2010-11-17 07:35:35 +00:00
|
|
|
mSubtypeSwitcher.getInputLocale());
|
2010-11-11 07:03:19 +00:00
|
|
|
|
2010-11-11 23:28:14 +00:00
|
|
|
keyboard = new LatinKeyboard(mInputMethodService, id);
|
2009-10-22 21:51:39 +00:00
|
|
|
|
2009-04-16 19:56:10 +00:00
|
|
|
if (id.mEnableShiftLock) {
|
|
|
|
keyboard.enableShiftLock();
|
|
|
|
}
|
2010-11-11 07:03:19 +00:00
|
|
|
|
|
|
|
mKeyboardCache.put(id, new SoftReference<LatinKeyboard>(keyboard));
|
|
|
|
if (DEBUG)
|
|
|
|
Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": "
|
|
|
|
+ ((ref == null) ? "LOAD" : "GCed") + " id=" + id);
|
2009-10-12 20:48:35 +00:00
|
|
|
|
2011-04-27 06:43:03 +00:00
|
|
|
Utils.setSystemLocale(res, savedLocale);
|
2010-11-11 07:03:19 +00:00
|
|
|
} else if (DEBUG) {
|
|
|
|
Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT id=" + id);
|
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);
|
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);
|
2011-04-22 09:00:16 +00:00
|
|
|
keyboard.setSpacebarSlidingLanguageSwitchDiff(0);
|
2010-09-08 16:41:58 +00:00
|
|
|
return keyboard;
|
2009-04-16 19:56:10 +00:00
|
|
|
}
|
|
|
|
|
2011-02-23 11:31:08 +00:00
|
|
|
private boolean hasVoiceKey(boolean isSymbols) {
|
|
|
|
return mVoiceKeyEnabled && (isSymbols != mVoiceButtonOnPrimary);
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean hasSettingsKey(EditorInfo attribute) {
|
|
|
|
return mSettingsKeyEnabledInSettings
|
|
|
|
&& !Utils.inPrivateImeOptions(mInputMethodService.getPackageName(),
|
|
|
|
LatinIME.IME_OPTION_NO_SETTINGS_KEY, attribute);
|
|
|
|
}
|
|
|
|
|
2011-02-20 13:04:50 +00:00
|
|
|
private KeyboardId getKeyboardId(EditorInfo attribute, boolean isSymbols) {
|
|
|
|
final int mode = Utils.getKeyboardMode(attribute);
|
2010-11-11 07:03:19 +00:00
|
|
|
final boolean hasVoiceKey = hasVoiceKey(isSymbols);
|
2010-11-22 00:40:38 +00:00
|
|
|
final int charColorId = getColorScheme();
|
|
|
|
final int xmlId;
|
2010-10-19 15:18:50 +00:00
|
|
|
final boolean enableShiftLock;
|
|
|
|
|
|
|
|
if (isSymbols) {
|
2010-12-02 09:46:21 +00:00
|
|
|
if (mode == KeyboardId.MODE_PHONE) {
|
2010-11-24 01:55:22 +00:00
|
|
|
xmlId = R.xml.kbd_phone_symbols;
|
2010-12-02 09:46:21 +00:00
|
|
|
} else if (mode == KeyboardId.MODE_NUMBER) {
|
2010-11-24 01:55:22 +00:00
|
|
|
// Note: MODE_NUMBER keyboard layout has no "switch alpha symbol" key.
|
|
|
|
xmlId = R.xml.kbd_number;
|
|
|
|
} else {
|
|
|
|
xmlId = R.xml.kbd_symbols;
|
|
|
|
}
|
2010-10-19 15:18:50 +00:00
|
|
|
enableShiftLock = false;
|
2010-11-24 01:55:22 +00:00
|
|
|
} else {
|
2010-12-02 09:46:21 +00:00
|
|
|
if (mode == KeyboardId.MODE_PHONE) {
|
2010-11-24 01:55:22 +00:00
|
|
|
xmlId = R.xml.kbd_phone;
|
|
|
|
enableShiftLock = false;
|
2010-12-02 09:46:21 +00:00
|
|
|
} else if (mode == KeyboardId.MODE_NUMBER) {
|
2010-11-24 01:55:22 +00:00
|
|
|
xmlId = R.xml.kbd_number;
|
|
|
|
enableShiftLock = false;
|
|
|
|
} else {
|
|
|
|
xmlId = R.xml.kbd_qwerty;
|
|
|
|
enableShiftLock = true;
|
|
|
|
}
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|
2011-02-23 11:31:08 +00:00
|
|
|
final boolean hasSettingsKey = hasSettingsKey(attribute);
|
2010-12-14 06:31:47 +00:00
|
|
|
final Resources res = mInputMethodService.getResources();
|
|
|
|
final int orientation = res.getConfiguration().orientation;
|
2010-11-17 07:35:35 +00:00
|
|
|
final Locale locale = mSubtypeSwitcher.getInputLocale();
|
2010-12-14 06:31:47 +00:00
|
|
|
return new KeyboardId(
|
2011-02-20 03:54:14 +00:00
|
|
|
res.getResourceEntryName(xmlId), xmlId, charColorId, locale, orientation, mode,
|
2011-02-23 11:31:08 +00:00
|
|
|
attribute, hasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, enableShiftLock);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void makeSymbolsKeyboardIds(final int mode, EditorInfo attribute) {
|
|
|
|
final Locale locale = mSubtypeSwitcher.getInputLocale();
|
|
|
|
final Resources res = mInputMethodService.getResources();
|
|
|
|
final int orientation = res.getConfiguration().orientation;
|
|
|
|
final int colorScheme = getColorScheme();
|
|
|
|
final boolean hasVoiceKey = mVoiceKeyEnabled && !mVoiceButtonOnPrimary;
|
|
|
|
final boolean hasSettingsKey = hasSettingsKey(attribute);
|
|
|
|
// Note: This comment is only applied for phone number keyboard layout.
|
|
|
|
// On non-xlarge device, "@integer/key_switch_alpha_symbol" key code is used to switch
|
|
|
|
// between "phone keyboard" and "phone symbols keyboard". But on xlarge device,
|
|
|
|
// "@integer/key_shift" key code is used for that purpose in order to properly display
|
|
|
|
// "more" and "locked more" key labels. To achieve these behavior, we should initialize
|
|
|
|
// mSymbolsId and mSymbolsShiftedId to "phone keyboard" and "phone symbols keyboard"
|
|
|
|
// respectively here for xlarge device's layout switching.
|
|
|
|
int xmlId = mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone : R.xml.kbd_symbols;
|
|
|
|
final String xmlName = res.getResourceEntryName(xmlId);
|
|
|
|
mSymbolsId = new KeyboardId(xmlName, xmlId, colorScheme, locale, orientation, mode,
|
2011-04-07 07:12:00 +00:00
|
|
|
attribute, hasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, false);
|
2011-02-23 11:31:08 +00:00
|
|
|
xmlId = mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone_symbols : R.xml.kbd_symbols_shift;
|
|
|
|
mSymbolsShiftedId = new KeyboardId(xmlName, xmlId, colorScheme, locale, orientation, mode,
|
2011-04-07 07:12:00 +00:00
|
|
|
attribute, hasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, false);
|
2009-03-13 22:11:42 +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() {
|
2010-12-02 11:54:32 +00:00
|
|
|
return mCurrentId != null && mCurrentId.isAlphabetKeyboard();
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|
|
|
|
|
2010-11-13 08:01:13 +00:00
|
|
|
public boolean isInputViewShown() {
|
|
|
|
return mInputView != null && mInputView.isShown();
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isKeyboardAvailable() {
|
2010-11-13 08:16:34 +00:00
|
|
|
if (mInputView != null)
|
2011-02-20 12:12:51 +00:00
|
|
|
return mInputView.getKeyboard() != null;
|
2010-11-13 08:16:34 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-02-20 12:12:51 +00:00
|
|
|
public LatinKeyboard getLatinKeyboard() {
|
|
|
|
if (mInputView != null) {
|
|
|
|
final Keyboard keyboard = mInputView.getKeyboard();
|
|
|
|
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() {
|
2010-11-13 08:16:34 +00:00
|
|
|
LatinKeyboard latinKeyboard = getLatinKeyboard();
|
|
|
|
if (latinKeyboard != null)
|
2010-11-13 08:16:34 +00:00
|
|
|
return latinKeyboard.isShiftedOrShiftLocked();
|
2010-11-13 08:16:34 +00:00
|
|
|
return false;
|
2010-11-13 08:01:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isShiftLocked() {
|
2010-11-13 08:16:34 +00:00
|
|
|
LatinKeyboard latinKeyboard = getLatinKeyboard();
|
|
|
|
if (latinKeyboard != null)
|
|
|
|
return latinKeyboard.isShiftLocked();
|
|
|
|
return false;
|
2010-11-13 08:01:13 +00:00
|
|
|
}
|
|
|
|
|
2010-11-13 08:16:34 +00:00
|
|
|
public boolean isAutomaticTemporaryUpperCase() {
|
|
|
|
LatinKeyboard latinKeyboard = getLatinKeyboard();
|
|
|
|
if (latinKeyboard != null)
|
|
|
|
return latinKeyboard.isAutomaticTemporaryUpperCase();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isManualTemporaryUpperCase() {
|
|
|
|
LatinKeyboard latinKeyboard = getLatinKeyboard();
|
|
|
|
if (latinKeyboard != null)
|
|
|
|
return latinKeyboard.isManualTemporaryUpperCase();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-01-18 09:12:44 +00:00
|
|
|
private boolean isManualTemporaryUpperCaseFromAuto() {
|
|
|
|
LatinKeyboard latinKeyboard = getLatinKeyboard();
|
|
|
|
if (latinKeyboard != null)
|
|
|
|
return latinKeyboard.isManualTemporaryUpperCaseFromAuto();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-11-13 08:16:34 +00:00
|
|
|
private void setManualTemporaryUpperCase(boolean shifted) {
|
2010-11-13 08:16:34 +00:00
|
|
|
LatinKeyboard latinKeyboard = getLatinKeyboard();
|
2010-11-23 01:20:48 +00:00
|
|
|
if (latinKeyboard != null) {
|
|
|
|
// 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.
|
|
|
|
// 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-01-14 18:49:21 +00:00
|
|
|
if ((!hasDistinctMultitouch() || isAccessibilityEnabled())
|
|
|
|
&& !shifted && latinKeyboard.isShiftLocked()) {
|
2010-11-23 01:20:48 +00:00
|
|
|
latinKeyboard.setShiftLocked(false);
|
|
|
|
}
|
|
|
|
if (latinKeyboard.setShifted(shifted)) {
|
|
|
|
mInputView.invalidateAllKeys();
|
|
|
|
}
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-13 08:16:34 +00:00
|
|
|
private void setShiftLocked(boolean shiftLocked) {
|
|
|
|
LatinKeyboard latinKeyboard = getLatinKeyboard();
|
|
|
|
if (latinKeyboard != null && latinKeyboard.setShiftLocked(shiftLocked)) {
|
|
|
|
mInputView.invalidateAllKeys();
|
|
|
|
}
|
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() {
|
|
|
|
mInputMethodService.mHandler.cancelUpdateShiftState();
|
2010-11-13 08:16:34 +00:00
|
|
|
if (DEBUG_STATE)
|
|
|
|
Log.d(TAG, "toggleShift:"
|
|
|
|
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
|
|
|
|
+ " shiftKeyState=" + mShiftKeyState);
|
2010-11-13 08:16:34 +00:00
|
|
|
if (isAlphabetMode()) {
|
2010-11-13 08:16:34 +00:00
|
|
|
setManualTemporaryUpperCase(!isShiftedOrShiftLocked());
|
2010-11-13 08:16:34 +00:00
|
|
|
} else {
|
|
|
|
toggleShiftInSymbol();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void toggleCapsLock() {
|
|
|
|
mInputMethodService.mHandler.cancelUpdateShiftState();
|
2010-11-13 08:16:34 +00:00
|
|
|
if (DEBUG_STATE)
|
|
|
|
Log.d(TAG, "toggleCapsLock:"
|
|
|
|
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
|
|
|
|
+ " shiftKeyState=" + mShiftKeyState);
|
2010-11-13 08:16:34 +00:00
|
|
|
if (isAlphabetMode()) {
|
|
|
|
if (isShiftLocked()) {
|
2010-11-13 08:16:34 +00:00
|
|
|
// Shift key is long pressed while caps lock state, we will toggle back to normal
|
|
|
|
// state. And mark as if shift key is released.
|
|
|
|
setShiftLocked(false);
|
|
|
|
mShiftKeyState.onRelease();
|
2010-11-13 08:16:34 +00:00
|
|
|
} else {
|
|
|
|
setShiftLocked(true);
|
|
|
|
}
|
|
|
|
}
|
2010-11-16 09:47:39 +00:00
|
|
|
}
|
|
|
|
|
2010-11-13 08:16:34 +00:00
|
|
|
private void setAutomaticTemporaryUpperCase() {
|
|
|
|
LatinKeyboard latinKeyboard = getLatinKeyboard();
|
|
|
|
if (latinKeyboard != null) {
|
|
|
|
latinKeyboard.setAutomaticTemporaryUpperCase();
|
|
|
|
mInputView.invalidateAllKeys();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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() {
|
2010-11-12 23:49:56 +00:00
|
|
|
final ShiftKeyState shiftKeyState = mShiftKeyState;
|
2010-11-13 08:16:34 +00:00
|
|
|
if (DEBUG_STATE)
|
|
|
|
Log.d(TAG, "updateShiftState:"
|
|
|
|
+ " autoCaps=" + mInputMethodService.getCurrentAutoCapsState()
|
|
|
|
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
|
2010-11-12 23:49:56 +00:00
|
|
|
+ " shiftKeyState=" + shiftKeyState);
|
|
|
|
if (isAlphabetMode()) {
|
|
|
|
if (!isShiftLocked() && !shiftKeyState.isIgnoring()) {
|
|
|
|
if (shiftKeyState.isReleasing() && mInputMethodService.getCurrentAutoCapsState()) {
|
|
|
|
// Only when shift key is releasing, automatic temporary upper case will be set.
|
|
|
|
setAutomaticTemporaryUpperCase();
|
|
|
|
} else {
|
|
|
|
setManualTemporaryUpperCase(shiftKeyState.isMomentary());
|
|
|
|
}
|
2010-11-13 08:16:34 +00:00
|
|
|
}
|
2010-11-12 23:49:56 +00:00
|
|
|
} else {
|
|
|
|
// In symbol keyboard mode, we should clear shift key state because only alphabet
|
|
|
|
// keyboard has shift key.
|
|
|
|
shiftKeyState.onRelease();
|
2010-11-13 08:16:34 +00:00
|
|
|
}
|
2010-11-16 09:47:39 +00:00
|
|
|
}
|
|
|
|
|
2010-11-13 08:16:34 +00:00
|
|
|
public void changeKeyboardMode() {
|
2010-11-13 08:16:34 +00:00
|
|
|
if (DEBUG_STATE)
|
|
|
|
Log.d(TAG, "changeKeyboardMode:"
|
|
|
|
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
|
|
|
|
+ " shiftKeyState=" + mShiftKeyState);
|
2010-11-13 08:16:34 +00:00
|
|
|
toggleKeyboardMode();
|
|
|
|
if (isShiftLocked() && isAlphabetMode())
|
|
|
|
setShiftLocked(true);
|
|
|
|
updateShiftState();
|
2010-11-16 09:47:39 +00:00
|
|
|
}
|
|
|
|
|
2011-03-02 19:43:13 +00:00
|
|
|
public void onPressShift(boolean withSliding) {
|
2010-11-13 08:16:34 +00:00
|
|
|
if (!isKeyboardAvailable())
|
|
|
|
return;
|
2011-01-14 18:49:21 +00:00
|
|
|
// If accessibility is enabled, disable momentary shift lock.
|
|
|
|
if (isAccessibilityEnabled())
|
|
|
|
return;
|
2010-11-13 08:16:34 +00:00
|
|
|
ShiftKeyState shiftKeyState = mShiftKeyState;
|
|
|
|
if (DEBUG_STATE)
|
|
|
|
Log.d(TAG, "onPressShift:"
|
|
|
|
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
|
2011-03-02 19:43:13 +00:00
|
|
|
+ " shiftKeyState=" + shiftKeyState + " sliding=" + withSliding);
|
2010-11-13 08:16:34 +00:00
|
|
|
if (isAlphabetMode()) {
|
|
|
|
if (isShiftLocked()) {
|
|
|
|
// Shift key is pressed while caps lock state, we will treat this state as shifted
|
|
|
|
// caps lock state and mark as if shift key pressed while normal state.
|
|
|
|
shiftKeyState.onPress();
|
2010-11-19 21:52:58 +00:00
|
|
|
setManualTemporaryUpperCase(true);
|
2010-11-13 08:16:34 +00:00
|
|
|
} else if (isAutomaticTemporaryUpperCase()) {
|
|
|
|
// Shift key is pressed while automatic temporary upper case, we have to move to
|
|
|
|
// manual temporary upper case.
|
2010-11-19 21:52:58 +00:00
|
|
|
shiftKeyState.onPress();
|
2010-11-13 08:16:34 +00:00
|
|
|
setManualTemporaryUpperCase(true);
|
|
|
|
} else if (isShiftedOrShiftLocked()) {
|
|
|
|
// In manual upper case state, we just record shift key has been pressing while
|
|
|
|
// shifted state.
|
|
|
|
shiftKeyState.onPressOnShifted();
|
|
|
|
} else {
|
|
|
|
// In base layout, chording or manual temporary upper case mode is started.
|
|
|
|
shiftKeyState.onPress();
|
2010-11-19 21:52:58 +00:00
|
|
|
toggleShift();
|
2010-11-13 08:16:34 +00:00
|
|
|
}
|
2010-11-13 08:16:34 +00:00
|
|
|
} else {
|
2010-11-13 08:16:34 +00:00
|
|
|
// In symbol mode, just toggle symbol and symbol more keyboard.
|
|
|
|
shiftKeyState.onPress();
|
2010-11-19 21:52:58 +00:00
|
|
|
toggleShift();
|
2011-04-26 05:27:35 +00:00
|
|
|
mSwitchState = SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE;
|
2010-11-13 08:16:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-02 19:43:13 +00:00
|
|
|
public void onReleaseShift(boolean withSliding) {
|
2010-11-13 08:16:34 +00:00
|
|
|
if (!isKeyboardAvailable())
|
|
|
|
return;
|
2011-01-14 18:49:21 +00:00
|
|
|
// If accessibility is enabled, disable momentary shift lock.
|
|
|
|
if (isAccessibilityEnabled())
|
|
|
|
return;
|
2010-11-13 08:16:34 +00:00
|
|
|
ShiftKeyState shiftKeyState = mShiftKeyState;
|
|
|
|
if (DEBUG_STATE)
|
|
|
|
Log.d(TAG, "onReleaseShift:"
|
|
|
|
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
|
2011-03-02 19:43:13 +00:00
|
|
|
+ " shiftKeyState=" + shiftKeyState + " sliding=" + withSliding);
|
2010-11-13 08:16:34 +00:00
|
|
|
if (isAlphabetMode()) {
|
2010-11-13 08:16:34 +00:00
|
|
|
if (shiftKeyState.isMomentary()) {
|
|
|
|
// After chording input while normal state.
|
|
|
|
toggleShift();
|
2011-03-02 19:43:13 +00:00
|
|
|
} else if (isShiftLocked() && !shiftKeyState.isIgnoring() && !withSliding) {
|
2010-11-13 08:16:34 +00:00
|
|
|
// Shift has been pressed without chording while caps lock state.
|
|
|
|
toggleCapsLock();
|
2011-04-26 10:49:34 +00:00
|
|
|
// 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.
|
|
|
|
mInputView.startIgnoringDoubleTap();
|
2011-03-02 19:43:13 +00:00
|
|
|
} else if (isShiftedOrShiftLocked() && shiftKeyState.isPressingOnShifted()
|
|
|
|
&& !withSliding) {
|
2010-11-13 08:16:34 +00:00
|
|
|
// Shift has been pressed without chording while shifted state.
|
2010-11-13 08:16:34 +00:00
|
|
|
toggleShift();
|
2011-03-02 19:43:13 +00:00
|
|
|
} else if (isManualTemporaryUpperCaseFromAuto() && shiftKeyState.isPressing()
|
|
|
|
&& !withSliding) {
|
2011-01-18 09:12:44 +00:00
|
|
|
// Shift has been pressed without chording while manual temporary upper case
|
|
|
|
// transited from automatic temporary upper case.
|
|
|
|
toggleShift();
|
2010-11-13 08:16:34 +00:00
|
|
|
}
|
2011-04-26 05:27:35 +00:00
|
|
|
} else {
|
|
|
|
// In symbol mode, snap back to the previous keyboard mode if the user chords the shift
|
|
|
|
// key and another key, then releases the shift key.
|
|
|
|
if (mSwitchState == SWITCH_STATE_CHORDING_SYMBOL) {
|
|
|
|
toggleShift();
|
|
|
|
}
|
2010-11-13 08:16:34 +00:00
|
|
|
}
|
2010-11-13 08:16:34 +00:00
|
|
|
shiftKeyState.onRelease();
|
2010-11-16 09:47:39 +00:00
|
|
|
}
|
|
|
|
|
2010-11-16 08:28:50 +00:00
|
|
|
public void onPressSymbol() {
|
2011-01-14 18:49:21 +00:00
|
|
|
// If accessibility is enabled, disable momentary symbol lock.
|
|
|
|
if (isAccessibilityEnabled())
|
|
|
|
return;
|
2010-11-13 08:16:34 +00:00
|
|
|
if (DEBUG_STATE)
|
2010-12-17 07:56:15 +00:00
|
|
|
Log.d(TAG, "onPressSymbol:"
|
2010-11-13 08:16:34 +00:00
|
|
|
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
|
|
|
|
+ " symbolKeyState=" + mSymbolKeyState);
|
2010-11-13 08:16:34 +00:00
|
|
|
changeKeyboardMode();
|
2010-11-16 08:28:50 +00:00
|
|
|
mSymbolKeyState.onPress();
|
2011-04-26 05:27:35 +00:00
|
|
|
mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL;
|
2010-11-16 08:28:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void onReleaseSymbol() {
|
2011-01-14 18:49:21 +00:00
|
|
|
// If accessibility is enabled, disable momentary symbol lock.
|
|
|
|
if (isAccessibilityEnabled())
|
|
|
|
return;
|
2010-11-13 08:16:34 +00:00
|
|
|
if (DEBUG_STATE)
|
2010-12-17 07:56:15 +00:00
|
|
|
Log.d(TAG, "onReleaseSymbol:"
|
2010-11-13 08:16:34 +00:00
|
|
|
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
|
|
|
|
+ " symbolKeyState=" + mSymbolKeyState);
|
2010-12-17 07:56:15 +00:00
|
|
|
// Snap back to the previous keyboard mode if the user chords the mode change key and
|
2011-04-26 05:27:35 +00:00
|
|
|
// another key, then releases the mode change key.
|
|
|
|
if (mSwitchState == SWITCH_STATE_CHORDING_ALPHA) {
|
2010-11-13 08:16:34 +00:00
|
|
|
changeKeyboardMode();
|
2011-04-26 05:27:35 +00:00
|
|
|
}
|
2010-11-16 08:28:50 +00:00
|
|
|
mSymbolKeyState.onRelease();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void onOtherKeyPressed() {
|
2011-01-14 18:49:21 +00:00
|
|
|
// If accessibility is enabled, disable momentary mode locking.
|
|
|
|
if (isAccessibilityEnabled())
|
|
|
|
return;
|
2010-11-12 23:49:56 +00:00
|
|
|
if (DEBUG_STATE)
|
|
|
|
Log.d(TAG, "onOtherKeyPressed:"
|
|
|
|
+ " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
|
|
|
|
+ " shiftKeyState=" + mShiftKeyState
|
|
|
|
+ " symbolKeyState=" + mSymbolKeyState);
|
2010-11-13 08:16:34 +00:00
|
|
|
mShiftKeyState.onOtherKeyPressed();
|
2010-11-16 08:28:50 +00:00
|
|
|
mSymbolKeyState.onOtherKeyPressed();
|
|
|
|
}
|
|
|
|
|
2010-12-30 08:19:55 +00:00
|
|
|
public void onCancelInput() {
|
|
|
|
// Snap back to the previous keyboard mode if the user cancels sliding input.
|
2011-04-26 05:27:35 +00:00
|
|
|
if (getPointerCount() == 1) {
|
|
|
|
if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) {
|
|
|
|
changeKeyboardMode();
|
|
|
|
} else if (mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE) {
|
|
|
|
toggleShift();
|
|
|
|
}
|
|
|
|
}
|
2010-12-30 08:19:55 +00:00
|
|
|
}
|
|
|
|
|
2010-11-13 08:16:34 +00:00
|
|
|
private void toggleShiftInSymbol() {
|
2010-10-08 13:17:16 +00:00
|
|
|
if (isAlphabetMode())
|
|
|
|
return;
|
2010-11-11 07:03:19 +00:00
|
|
|
final LatinKeyboard keyboard;
|
2010-10-08 13:17:16 +00:00
|
|
|
if (mCurrentId.equals(mSymbolsId) || !mCurrentId.equals(mSymbolsShiftedId)) {
|
2009-04-16 19:56:10 +00:00
|
|
|
mCurrentId = mSymbolsShiftedId;
|
2010-11-11 07:03:19 +00:00
|
|
|
keyboard = getKeyboard(mCurrentId);
|
2010-09-06 05:50:50 +00:00
|
|
|
// Symbol shifted keyboard has an ALT key that has a caps lock style indicator. To
|
2011-04-07 07:12:00 +00:00
|
|
|
// enable the indicator, we need to call setShiftLocked(true).
|
2010-11-11 07:03:19 +00:00
|
|
|
keyboard.setShiftLocked(true);
|
2010-10-08 13:17:16 +00:00
|
|
|
} else {
|
2009-04-16 19:56:10 +00:00
|
|
|
mCurrentId = mSymbolsId;
|
2010-11-11 07:03:19 +00:00
|
|
|
keyboard = getKeyboard(mCurrentId);
|
2010-09-06 05:50:50 +00:00
|
|
|
// Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the
|
2011-04-07 07:12:00 +00:00
|
|
|
// indicator, we need to call setShiftLocked(false).
|
|
|
|
keyboard.setShiftLocked(false);
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|
2011-02-20 12:12:51 +00:00
|
|
|
setKeyboard(keyboard);
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|
|
|
|
|
2011-04-26 05:27:35 +00:00
|
|
|
public boolean isInMomentarySwitchState() {
|
|
|
|
return mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL
|
|
|
|
|| mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE;
|
2010-12-17 07:56:15 +00:00
|
|
|
}
|
|
|
|
|
2010-12-20 07:21:54 +00:00
|
|
|
public boolean isVibrateAndSoundFeedbackRequired() {
|
|
|
|
return mInputView == null || !mInputView.isInSlidingKeyInput();
|
|
|
|
}
|
|
|
|
|
2010-12-17 07:56:15 +00:00
|
|
|
private int getPointerCount() {
|
|
|
|
return mInputView == null ? 0 : mInputView.getPointerCount();
|
|
|
|
}
|
|
|
|
|
2010-11-13 08:16:34 +00:00
|
|
|
private void toggleKeyboardMode() {
|
2011-02-20 13:04:50 +00:00
|
|
|
loadKeyboardInternal(mAttribute, mVoiceKeyEnabled, mVoiceButtonOnPrimary, !mIsSymbols);
|
2010-10-19 15:18:50 +00:00
|
|
|
if (mIsSymbols) {
|
2011-04-26 05:27:35 +00:00
|
|
|
mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
|
2009-07-21 22:47:11 +00:00
|
|
|
} else {
|
2011-04-26 05:27:35 +00:00
|
|
|
mSwitchState = SWITCH_STATE_ALPHA;
|
2009-07-21 22:47:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-14 18:49:21 +00:00
|
|
|
public boolean isAccessibilityEnabled() {
|
|
|
|
return mInputView != null && mInputView.isAccessibilityEnabled();
|
|
|
|
}
|
|
|
|
|
2010-09-06 05:26:46 +00:00
|
|
|
public boolean hasDistinctMultitouch() {
|
|
|
|
return mInputView != null && mInputView.hasDistinctMultitouch();
|
|
|
|
}
|
|
|
|
|
2011-04-26 05:27:35 +00:00
|
|
|
private static boolean isSpaceCharacter(int c) {
|
|
|
|
return c == Keyboard.CODE_SPACE || c == Keyboard.CODE_ENTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static boolean isQuoteCharacter(int c) {
|
|
|
|
// Apostrophe, quotation mark.
|
2011-04-28 06:39:39 +00:00
|
|
|
if (c == Keyboard.CODE_SINGLE_QUOTE || c == Keyboard.CODE_DOUBLE_QUOTE)
|
2011-04-26 05:27:35 +00:00
|
|
|
return true;
|
|
|
|
// \u2018: Left single quotation mark
|
|
|
|
// \u2019: Right single quotation mark
|
|
|
|
// \u201a: Single low-9 quotation mark
|
|
|
|
// \u201b: Single high-reversed-9 quotation mark
|
|
|
|
// \u201c: Left double quotation mark
|
|
|
|
// \u201d: Right double quotation mark
|
|
|
|
// \u201e: Double low-9 quotation mark
|
|
|
|
// \u201f: Double high-reversed-9 quotation mark
|
|
|
|
if (c >= '\u2018' && c <= '\u201f')
|
|
|
|
return true;
|
|
|
|
// \u00ab: Left-pointing double angle quotation mark
|
|
|
|
// \u00bb: Right-pointing double angle quotation mark
|
|
|
|
if (c == '\u00ab' || c == '\u00bb')
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
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-04-26 05:27:35 +00:00
|
|
|
public void onKey(int code) {
|
2010-12-17 07:56:15 +00:00
|
|
|
if (DEBUG_STATE)
|
2011-04-26 05:27:35 +00:00
|
|
|
Log.d(TAG, "onKey: code=" + code + " switchState=" + mSwitchState
|
2010-12-17 07:56:15 +00:00
|
|
|
+ " pointers=" + getPointerCount());
|
2011-04-26 05:27:35 +00:00
|
|
|
switch (mSwitchState) {
|
|
|
|
case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL:
|
2010-12-17 07:56:15 +00:00
|
|
|
// Only distinct multi touch devices can be in this state.
|
2010-12-30 08:19:55 +00:00
|
|
|
// On non-distinct multi touch devices, mode change key is handled by
|
|
|
|
// {@link LatinIME#onCodeInput}, not by {@link LatinIME#onPress} and
|
2011-04-26 05:27:35 +00:00
|
|
|
// {@link LatinIME#onRelease}. So, on such devices, {@link #mSwitchState} starts
|
|
|
|
// from {@link #SWITCH_STATE_SYMBOL_BEGIN}, or {@link #SWITCH_STATE_ALPHA}, not from
|
|
|
|
// {@link #SWITCH_STATE_MOMENTARY}.
|
|
|
|
if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
|
2010-12-17 07:56:15 +00:00
|
|
|
// Detected only the mode change key has been pressed, and then released.
|
|
|
|
if (mIsSymbols) {
|
2011-04-26 05:27:35 +00:00
|
|
|
mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
|
2010-12-17 07:56:15 +00:00
|
|
|
} else {
|
2011-04-26 05:27:35 +00:00
|
|
|
mSwitchState = SWITCH_STATE_ALPHA;
|
2010-12-17 07:56:15 +00:00
|
|
|
}
|
|
|
|
} else if (getPointerCount() == 1) {
|
|
|
|
// Snap back to the previous keyboard mode if the user pressed the mode change key
|
|
|
|
// and slid to other key, then released the finger.
|
2010-12-30 08:19:55 +00:00
|
|
|
// If the user cancels the sliding input, snapping back to the previous keyboard
|
|
|
|
// mode is handled by {@link #onCancelInput}.
|
2010-12-17 07:56:15 +00:00
|
|
|
changeKeyboardMode();
|
|
|
|
} else {
|
|
|
|
// Chording input is being started. The keyboard mode will be snapped back to the
|
|
|
|
// previous mode in {@link onReleaseSymbol} when the mode change key is released.
|
2011-04-26 05:27:35 +00:00
|
|
|
mSwitchState = SWITCH_STATE_CHORDING_ALPHA;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE:
|
|
|
|
if (code == Keyboard.CODE_SHIFT) {
|
|
|
|
// Detected only the shift key has been pressed on symbol layout, and then released.
|
|
|
|
mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
|
|
|
|
} else if (getPointerCount() == 1) {
|
|
|
|
// Snap back to the previous keyboard mode if the user pressed the shift key on
|
|
|
|
// symbol mode and slid to other key, then released the finger.
|
|
|
|
toggleShift();
|
|
|
|
mSwitchState = SWITCH_STATE_SYMBOL;
|
|
|
|
} else {
|
|
|
|
// Chording input is being started. The keyboard mode will be snapped back to the
|
|
|
|
// previous mode in {@link onReleaseShift} when the shift key is released.
|
|
|
|
mSwitchState = SWITCH_STATE_CHORDING_SYMBOL;
|
2010-12-17 07:56:15 +00:00
|
|
|
}
|
|
|
|
break;
|
2011-04-26 05:27:35 +00:00
|
|
|
case SWITCH_STATE_SYMBOL_BEGIN:
|
|
|
|
if (!isSpaceCharacter(code) && code >= 0) {
|
|
|
|
mSwitchState = SWITCH_STATE_SYMBOL;
|
2010-11-13 08:16:34 +00:00
|
|
|
}
|
2011-04-27 10:10:32 +00:00
|
|
|
// Snap back to alpha keyboard mode immediately if user types a quote character.
|
|
|
|
if (isQuoteCharacter(code)) {
|
|
|
|
changeKeyboardMode();
|
|
|
|
}
|
2010-11-13 08:16:34 +00:00
|
|
|
break;
|
2011-04-26 05:27:35 +00:00
|
|
|
case SWITCH_STATE_SYMBOL:
|
|
|
|
case SWITCH_STATE_CHORDING_SYMBOL:
|
2010-12-17 07:56:15 +00:00
|
|
|
// Snap back to alpha keyboard mode if user types one or more non-space/enter
|
2011-04-27 10:10:32 +00:00
|
|
|
// characters followed by a space/enter or a quote character.
|
2011-04-26 05:27:35 +00:00
|
|
|
if (isSpaceCharacter(code) || isQuoteCharacter(code)) {
|
2010-11-13 08:16:34 +00:00
|
|
|
changeKeyboardMode();
|
|
|
|
}
|
|
|
|
break;
|
2009-07-21 22:47:11 +00:00
|
|
|
}
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|
2010-08-20 05:35:02 +00:00
|
|
|
|
|
|
|
public LatinKeyboardView getInputView() {
|
|
|
|
return mInputView;
|
|
|
|
}
|
|
|
|
|
2010-11-25 01:02:50 +00:00
|
|
|
public LatinKeyboardView onCreateInputView() {
|
|
|
|
createInputViewInternal(mLayoutId, true);
|
|
|
|
return mInputView;
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
|
|
|
|
2010-11-25 01:02:50 +00:00
|
|
|
private void createInputViewInternal(int newLayout, boolean forceReset) {
|
2010-12-10 06:24:28 +00:00
|
|
|
int layoutId = newLayout;
|
|
|
|
if (mLayoutId != layoutId || mInputView == null || forceReset) {
|
2010-08-20 05:35:02 +00:00
|
|
|
if (mInputView != null) {
|
|
|
|
mInputView.closing();
|
|
|
|
}
|
2010-12-28 11:49:58 +00:00
|
|
|
if (KEYBOARD_THEMES.length <= layoutId) {
|
|
|
|
layoutId = Integer.valueOf(sConfigDefaultKeyboardThemeId);
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
|
|
|
|
2010-12-09 12:06:26 +00:00
|
|
|
Utils.GCUtils.getInstance().reset();
|
2010-08-20 05:35:02 +00:00
|
|
|
boolean tryGC = true;
|
2010-12-09 12:06:26 +00:00
|
|
|
for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
|
2010-08-20 05:35:02 +00:00
|
|
|
try {
|
|
|
|
mInputView = (LatinKeyboardView) mInputMethodService.getLayoutInflater(
|
2010-12-28 11:49:58 +00:00
|
|
|
).inflate(KEYBOARD_THEMES[layoutId], null);
|
2010-08-20 05:35:02 +00:00
|
|
|
tryGC = false;
|
|
|
|
} catch (OutOfMemoryError e) {
|
2010-11-24 07:59:56 +00:00
|
|
|
Log.w(TAG, "load keyboard failed: " + e);
|
2010-12-09 12:06:26 +00:00
|
|
|
tryGC = Utils.GCUtils.getInstance().tryGCOrWait(
|
2010-12-10 06:24:28 +00:00
|
|
|
mLayoutId + "," + layoutId, e);
|
2010-08-20 05:35:02 +00:00
|
|
|
} catch (InflateException e) {
|
2010-11-24 07:59:56 +00:00
|
|
|
Log.w(TAG, "load keyboard failed: " + e);
|
2010-12-09 12:06:26 +00:00
|
|
|
tryGC = Utils.GCUtils.getInstance().tryGCOrWait(
|
2010-12-10 06:24:28 +00:00
|
|
|
mLayoutId + "," + layoutId, e);
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
mInputView.setOnKeyboardActionListener(mInputMethodService);
|
2010-12-10 06:24:28 +00:00
|
|
|
mLayoutId = layoutId;
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
2010-11-25 01:02:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void postSetInputView() {
|
2010-08-20 05:35:02 +00:00
|
|
|
mInputMethodService.mHandler.post(new Runnable() {
|
2010-11-25 01:02:50 +00:00
|
|
|
@Override
|
2010-08-20 05:35:02 +00:00
|
|
|
public void run() {
|
|
|
|
if (mInputView != null) {
|
|
|
|
mInputMethodService.setInputView(mInputView);
|
|
|
|
}
|
|
|
|
mInputMethodService.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)) {
|
2010-11-11 07:03:19 +00:00
|
|
|
final int layoutId = Integer.valueOf(
|
2010-12-28 11:49:58 +00:00
|
|
|
sharedPreferences.getString(key, sConfigDefaultKeyboardThemeId));
|
2010-11-25 01:02:50 +00:00
|
|
|
createInputViewInternal(layoutId, false);
|
|
|
|
postSetInputView();
|
2010-12-09 12:06:26 +00:00
|
|
|
} else if (Settings.PREF_SETTINGS_KEY.equals(key)) {
|
2011-02-23 11:31:08 +00:00
|
|
|
mSettingsKeyEnabledInSettings = getSettingsKeyMode(sharedPreferences,
|
|
|
|
mInputMethodService);
|
2010-11-25 01:02:50 +00:00
|
|
|
createInputViewInternal(mLayoutId, true);
|
|
|
|
postSetInputView();
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-22 00:40:38 +00:00
|
|
|
private int getColorScheme() {
|
|
|
|
return (mInputView != null)
|
2010-12-02 09:46:21 +00:00
|
|
|
? mInputView.getColorScheme() : KeyboardView.COLOR_SCHEME_WHITE;
|
2010-08-20 05:35:02 +00:00
|
|
|
}
|
|
|
|
|
2010-12-11 08:06:24 +00:00
|
|
|
public void onAutoCorrectionStateChanged(boolean isAutoCorrection) {
|
|
|
|
if (isAutoCorrection != mIsAutoCorrectionActive) {
|
2010-09-02 13:54:37 +00:00
|
|
|
LatinKeyboardView keyboardView = getInputView();
|
2010-12-11 08:06:24 +00:00
|
|
|
mIsAutoCorrectionActive = isAutoCorrection;
|
2010-09-02 13:54:37 +00:00
|
|
|
keyboardView.invalidateKey(((LatinKeyboard) keyboardView.getKeyboard())
|
2010-12-11 08:06:24 +00:00
|
|
|
.onAutoCorrectionStateChanged(isAutoCorrection));
|
2010-09-02 13:54:37 +00:00
|
|
|
}
|
|
|
|
}
|
2010-09-15 04:37:52 +00:00
|
|
|
|
2010-11-11 07:03:19 +00:00
|
|
|
private static boolean getSettingsKeyMode(SharedPreferences prefs, Context context) {
|
|
|
|
Resources resources = context.getResources();
|
2010-10-22 05:28:12 +00:00
|
|
|
final boolean showSettingsKeyOption = resources.getBoolean(
|
|
|
|
R.bool.config_enable_show_settings_key_option);
|
2010-11-02 09:55:20 +00:00
|
|
|
if (showSettingsKeyOption) {
|
2010-12-09 12:06:26 +00:00
|
|
|
final String settingsKeyMode = prefs.getString(Settings.PREF_SETTINGS_KEY,
|
2010-11-02 09:55:20 +00:00
|
|
|
resources.getString(DEFAULT_SETTINGS_KEY_MODE));
|
|
|
|
// We show the settings key when 1) SETTINGS_KEY_MODE_ALWAYS_SHOW or
|
|
|
|
// 2) SETTINGS_KEY_MODE_AUTO and there are two or more enabled IMEs on the system
|
|
|
|
if (settingsKeyMode.equals(resources.getString(SETTINGS_KEY_MODE_ALWAYS_SHOW))
|
|
|
|
|| (settingsKeyMode.equals(resources.getString(SETTINGS_KEY_MODE_AUTO))
|
2010-12-09 12:06:26 +00:00
|
|
|
&& Utils.hasMultipleEnabledIMEsOrSubtypes(
|
2011-03-18 05:49:06 +00:00
|
|
|
(InputMethodManagerCompatWrapper.getInstance(context))))) {
|
2010-11-11 07:03:19 +00:00
|
|
|
return true;
|
2010-11-02 09:55:20 +00:00
|
|
|
}
|
2011-02-23 11:31:08 +00:00
|
|
|
return false;
|
2010-09-15 04:37:52 +00:00
|
|
|
}
|
2011-02-23 11:31:08 +00:00
|
|
|
// If the show settings key option is disabled, we always try showing the settings key.
|
|
|
|
return true;
|
2010-09-15 04:37:52 +00:00
|
|
|
}
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|