Clean up keyboard loading and switching

Bug: 4311428
Change-Id: Ia72de23634f824d82b7b5f2267d439ce922a3b57
main
Tadashi G. Takaoka 2011-07-26 17:22:58 -07:00
parent a48f8b3764
commit 60ccbe16ee
8 changed files with 72 additions and 106 deletions

View File

@ -91,12 +91,12 @@
latin:parentStyle="numKeyStyle" /> latin:parentStyle="numKeyStyle" />
<key-style <key-style
latin:styleName="numSwitchToAltKeyStyle" latin:styleName="numSwitchToAltKeyStyle"
latin:code="@integer/key_switch_alpha_symbol" latin:code="@integer/key_shift"
latin:keyLabel="@string/label_to_phone_symbols_key" latin:keyLabel="@string/label_to_phone_symbols_key"
latin:parentStyle="numModeKeyStyle" /> latin:parentStyle="numModeKeyStyle" />
<key-style <key-style
latin:styleName="numSwitchToNumericKeyStyle" latin:styleName="numSwitchToNumericKeyStyle"
latin:code="@integer/key_switch_alpha_symbol" latin:code="@integer/key_shift"
latin:keyLabel="@string/label_to_phone_numeric_key" latin:keyLabel="@string/label_to_phone_numeric_key"
latin:parentStyle="numModeKeyStyle" /> latin:parentStyle="numModeKeyStyle" />
<key-style <key-style

View File

@ -164,7 +164,7 @@ public class KeyCodeDescriptionMapper {
return context.getString(R.string.spoken_description_to_symbol); return context.getString(R.string.spoken_description_to_symbol);
} else if (id.isSymbolsKeyboard()) { } else if (id.isSymbolsKeyboard()) {
return context.getString(R.string.spoken_description_to_alpha); return context.getString(R.string.spoken_description_to_alpha);
} else if (id.isPhoneSymbolsKeyboard()) { } else if (id.isPhoneShiftKeyboard()) {
return context.getString(R.string.spoken_description_to_numeric); return context.getString(R.string.spoken_description_to_numeric);
} else if (id.isPhoneKeyboard()) { } else if (id.isPhoneKeyboard()) {
return context.getString(R.string.spoken_description_to_symbol); return context.getString(R.string.spoken_description_to_symbol);

View File

@ -119,12 +119,6 @@ public class KeyboardId {
mWidth, mMode, mAttribute, false, F2KEY_MODE_NONE, false, false, false, false); mWidth, mMode, mAttribute, false, F2KEY_MODE_NONE, false, false, false, false);
} }
public KeyboardId cloneWithNewLayout(String xmlName, int xmlId) {
return new KeyboardId(xmlName, xmlId, mLocale, mOrientation, mWidth, mMode, mAttribute,
mHasSettingsKey, mF2KeyMode, mClobberSettingsKey, mVoiceKeyEnabled, mHasVoiceKey,
mEnableShiftLock);
}
public KeyboardId cloneWithNewGeometry(int orientation, int width) { public KeyboardId cloneWithNewGeometry(int orientation, int width) {
if (mWidth == width) if (mWidth == width)
return this; return this;
@ -153,8 +147,8 @@ public class KeyboardId {
return mMode == MODE_PHONE; return mMode == MODE_PHONE;
} }
public boolean isPhoneSymbolsKeyboard() { public boolean isPhoneShiftKeyboard() {
return mXmlId == R.xml.kbd_phone_symbols; return mXmlId == R.xml.kbd_phone_shift;
} }
public boolean isNumberKeyboard() { public boolean isNumberKeyboard() {

View File

@ -67,20 +67,17 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift"); private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift");
private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol"); private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol");
private KeyboardId mSymbolsId; private KeyboardId mMainKeyboardId;
private KeyboardId mSymbolsShiftedId; private KeyboardId mSymbolsKeyboardId;
private KeyboardId mSymbolsShiftedKeyboardId;
private KeyboardId mCurrentId; private KeyboardId mCurrentId;
private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache = private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache =
new HashMap<KeyboardId, SoftReference<LatinKeyboard>>(); new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
private EditorInfo mAttribute;
private boolean mIsSymbols;
/** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of /** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of
* what user actually typed. */ * what user actually typed. */
private boolean mIsAutoCorrectionActive; private boolean mIsAutoCorrectionActive;
private boolean mVoiceKeyEnabled;
private boolean mVoiceButtonOnPrimary;
// TODO: Encapsulate these state handling to separate class and combine with ShiftKeyState // TODO: Encapsulate these state handling to separate class and combine with ShiftKeyState
// and ModifierKeyState. // and ModifierKeyState.
@ -94,8 +91,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private static final int SWITCH_STATE_CHORDING_SYMBOL = 6; private static final int SWITCH_STATE_CHORDING_SYMBOL = 6;
private int mSwitchState = SWITCH_STATE_ALPHA; private int mSwitchState = SWITCH_STATE_ALPHA;
// Indicates whether or not we have the settings key in option of settings
private boolean mSettingsKeyEnabledInSettings;
private static final int SETTINGS_KEY_MODE_AUTO = R.string.settings_key_mode_auto; private static final int SETTINGS_KEY_MODE_AUTO = R.string.settings_key_mode_auto;
private static final int SETTINGS_KEY_MODE_ALWAYS_SHOW = private static final int SETTINGS_KEY_MODE_ALWAYS_SHOW =
R.string.settings_key_mode_always_show; R.string.settings_key_mode_always_show;
@ -151,42 +146,21 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
public void loadKeyboard(EditorInfo attribute, Settings.Values settings) { public void loadKeyboard(EditorInfo attribute, Settings.Values settings) {
mSwitchState = SWITCH_STATE_ALPHA; mSwitchState = SWITCH_STATE_ALPHA;
try { try {
loadKeyboardInternal(attribute, settings.isVoiceButtonEnabled(attribute), final boolean voiceKeyEnabled = settings.isVoiceKeyEnabled(attribute);
settings.isVoiceButtonOnPrimary(), false); final boolean voiceKeyOnMain = settings.isVoiceKeyOnMain();
mMainKeyboardId = getKeyboardId(
attribute, false, false, voiceKeyEnabled, voiceKeyOnMain);
mSymbolsKeyboardId = getKeyboardId(
attribute, true, false, voiceKeyEnabled, voiceKeyOnMain);
mSymbolsShiftedKeyboardId = getKeyboardId(
attribute, true, true, voiceKeyEnabled, voiceKeyOnMain);
setKeyboard(getKeyboard(mMainKeyboardId));
} catch (RuntimeException e) { } catch (RuntimeException e) {
// Get KeyboardId to record which keyboard has been failed to load. Log.w(TAG, "loading keyboard failed: " + mMainKeyboardId, e);
final KeyboardId id = getKeyboardId(attribute, false); LatinImeLogger.logOnException(mMainKeyboardId.toString(), e);
Log.w(TAG, "loading keyboard failed: " + id, e);
LatinImeLogger.logOnException(id.toString(), e);
} }
} }
private void loadKeyboardInternal(EditorInfo attribute, boolean voiceButtonEnabled,
boolean voiceButtonOnPrimary, boolean isSymbols) {
if (mKeyboardView == null) return;
mAttribute = attribute;
mVoiceKeyEnabled = voiceButtonEnabled;
mVoiceButtonOnPrimary = voiceButtonOnPrimary;
mIsSymbols = isSymbols;
// Update the settings key state because number of enabled IMEs could have been changed
mSettingsKeyEnabledInSettings = getSettingsKeyMode(mPrefs, mInputMethodService);
final KeyboardId id = getKeyboardId(attribute, isSymbols);
// 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.
mSymbolsId = makeSiblingKeyboardId(id, R.xml.kbd_symbols, R.xml.kbd_phone);
mSymbolsShiftedId = makeSiblingKeyboardId(
id, R.xml.kbd_symbols_shift, R.xml.kbd_phone_symbols);
setKeyboard(getKeyboard(id));
}
@SuppressWarnings("unused") @SuppressWarnings("unused")
public void onSizeChanged(int w, int h, int oldw, int oldh) { public void onSizeChanged(int w, int h, int oldw, int oldh) {
final int width = mInputMethodService.getWindow().getWindow().getDecorView().getWidth(); final int width = mInputMethodService.getWindow().getWindow().getDecorView().getWidth();
@ -255,45 +229,40 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
return keyboard; return keyboard;
} }
private boolean hasVoiceKey(boolean isSymbols) { private static boolean hasSettingsKey(SharedPreferences prefs, Context context,
return mVoiceKeyEnabled && (isSymbols != mVoiceButtonOnPrimary); EditorInfo attribute) {
} return getSettingsKeyMode(prefs, context)
&& !Utils.inPrivateImeOptions(context.getPackageName(),
private boolean hasSettingsKey(EditorInfo attribute) {
return mSettingsKeyEnabledInSettings
&& !Utils.inPrivateImeOptions(mInputMethodService.getPackageName(),
LatinIME.IME_OPTION_NO_SETTINGS_KEY, attribute); LatinIME.IME_OPTION_NO_SETTINGS_KEY, attribute);
} }
private KeyboardId getKeyboardId(EditorInfo attribute, boolean isSymbols) { private KeyboardId getKeyboardId(EditorInfo attribute, final boolean isSymbols,
final boolean isShift, final boolean voiceKeyEnabled, final boolean voiceKeyOnMain) {
final int mode = Utils.getKeyboardMode(attribute); final int mode = Utils.getKeyboardMode(attribute);
final boolean hasVoiceKey = hasVoiceKey(isSymbols); final boolean hasVoiceKey = voiceKeyEnabled && (isSymbols != voiceKeyOnMain);
final int xmlId; final int xmlId;
final boolean enableShiftLock; final boolean enableShiftLock;
if (isSymbols) { switch (mode) {
if (mode == KeyboardId.MODE_PHONE) { case KeyboardId.MODE_PHONE:
xmlId = R.xml.kbd_phone_symbols; xmlId = (isSymbols && isShift) ? R.xml.kbd_phone_shift : R.xml.kbd_phone;
} else if (mode == KeyboardId.MODE_NUMBER) { enableShiftLock = true;
// Note: MODE_NUMBER keyboard layout has no "switch alpha symbol" key. break;
xmlId = R.xml.kbd_number; case KeyboardId.MODE_NUMBER:
} else { xmlId = R.xml.kbd_number;
xmlId = R.xml.kbd_symbols;
}
enableShiftLock = false; enableShiftLock = false;
} else { break;
if (mode == KeyboardId.MODE_PHONE) { default:
xmlId = R.xml.kbd_phone; if (isSymbols) {
enableShiftLock = false; xmlId = isShift ? R.xml.kbd_symbols_shift : R.xml.kbd_symbols;
} else if (mode == KeyboardId.MODE_NUMBER) {
xmlId = R.xml.kbd_number;
enableShiftLock = false;
} else { } else {
xmlId = R.xml.kbd_qwerty; xmlId = R.xml.kbd_qwerty;
enableShiftLock = true;
} }
enableShiftLock = true;
break;
} }
final boolean hasSettingsKey = hasSettingsKey(attribute);
final boolean hasSettingsKey = hasSettingsKey(mPrefs, mInputMethodService, attribute);
final int f2KeyMode = getF2KeyMode(mPrefs, mInputMethodService, attribute); final int f2KeyMode = getF2KeyMode(mPrefs, mInputMethodService, attribute);
final boolean clobberSettingsKey = Utils.inPrivateImeOptions( final boolean clobberSettingsKey = Utils.inPrivateImeOptions(
mInputMethodService.getPackageName(), LatinIME.IME_OPTION_NO_SETTINGS_KEY, mInputMethodService.getPackageName(), LatinIME.IME_OPTION_NO_SETTINGS_KEY,
@ -305,16 +274,10 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
final Locale locale = mSubtypeSwitcher.getInputLocale(); final Locale locale = mSubtypeSwitcher.getInputLocale();
return new KeyboardId( return new KeyboardId(
res.getResourceEntryName(xmlId), xmlId, locale, orientation, mWindowWidth, res.getResourceEntryName(xmlId), xmlId, locale, orientation, mWindowWidth,
mode, attribute, hasSettingsKey, f2KeyMode, clobberSettingsKey, mVoiceKeyEnabled, mode, attribute, hasSettingsKey, f2KeyMode, clobberSettingsKey, voiceKeyEnabled,
hasVoiceKey, enableShiftLock); hasVoiceKey, enableShiftLock);
} }
private KeyboardId makeSiblingKeyboardId(KeyboardId base, int alphabet, int phone) {
final int xmlId = base.mMode == KeyboardId.MODE_PHONE ? phone : alphabet;
final String xmlName = mInputMethodService.getResources().getResourceEntryName(xmlId);
return base.cloneWithNewLayout(xmlName, xmlId);
}
public int getKeyboardMode() { public int getKeyboardMode() {
return mCurrentId != null ? mCurrentId.mMode : KeyboardId.MODE_TEXT; return mCurrentId != null ? mCurrentId.mMode : KeyboardId.MODE_TEXT;
} }
@ -602,13 +565,15 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
if (isAlphabetMode()) if (isAlphabetMode())
return; return;
final LatinKeyboard keyboard; final LatinKeyboard keyboard;
if (mCurrentId.equals(mSymbolsId) || !mCurrentId.equals(mSymbolsShiftedId)) { if (mCurrentId.equals(mSymbolsKeyboardId)
keyboard = getKeyboard(mSymbolsShiftedId); || !mCurrentId.equals(mSymbolsShiftedKeyboardId)) {
// Symbol shifted keyboard has an ALT key that has a caps lock style indicator. To keyboard = getKeyboard(mSymbolsShiftedKeyboardId);
// enable the indicator, we need to call setShiftLocked(true). // Symbol keyboard may have an ALT key that has a caps lock style indicator (a.k.a.
keyboard.setShiftLocked(true); // 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(hasStickyShiftKey(keyboard));
} else { } else {
keyboard = getKeyboard(mSymbolsId); keyboard = getKeyboard(mSymbolsKeyboardId);
// Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the // Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the
// indicator, we need to call setShiftLocked(false). // indicator, we need to call setShiftLocked(false).
keyboard.setShiftLocked(false); keyboard.setShiftLocked(false);
@ -616,6 +581,14 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
setKeyboard(keyboard); setKeyboard(keyboard);
} }
private static boolean hasStickyShiftKey(Keyboard keyboard) {
for (final Key shiftKey : keyboard.getShiftKeys()) {
if (shiftKey.mSticky)
return true;
}
return false;
}
public boolean isInMomentarySwitchState() { public boolean isInMomentarySwitchState() {
return mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL return mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL
|| mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE; || mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE;
@ -630,10 +603,11 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
} }
private void toggleKeyboardMode() { private void toggleKeyboardMode() {
loadKeyboardInternal(mAttribute, mVoiceKeyEnabled, mVoiceButtonOnPrimary, !mIsSymbols); if (mCurrentId.equals(mMainKeyboardId)) {
if (mIsSymbols) { setKeyboard(getKeyboard(mSymbolsKeyboardId));
mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
} else { } else {
setKeyboard(getKeyboard(mMainKeyboardId));
mSwitchState = SWITCH_STATE_ALPHA; mSwitchState = SWITCH_STATE_ALPHA;
} }
} }
@ -684,10 +658,10 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
// {@link #SWITCH_STATE_MOMENTARY}. // {@link #SWITCH_STATE_MOMENTARY}.
if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
// Detected only the mode change key has been pressed, and then released. // Detected only the mode change key has been pressed, and then released.
if (mIsSymbols) { if (mCurrentId.equals(mMainKeyboardId)) {
mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
} else {
mSwitchState = SWITCH_STATE_ALPHA; mSwitchState = SWITCH_STATE_ALPHA;
} else {
mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
} }
} else if (getPointerCount() == 1) { } else if (getPointerCount() == 1) {
// Snap back to the previous keyboard mode if the user pressed the mode change key // Snap back to the previous keyboard mode if the user pressed the mode change key
@ -800,8 +774,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
final int layoutId = getKeyboardThemeIndex(mInputMethodService, sharedPreferences); final int layoutId = getKeyboardThemeIndex(mInputMethodService, sharedPreferences);
postSetInputView(createInputView(layoutId, false)); postSetInputView(createInputView(layoutId, false));
} else if (Settings.PREF_SETTINGS_KEY.equals(key)) { } else if (Settings.PREF_SETTINGS_KEY.equals(key)) {
mSettingsKeyEnabledInSettings = getSettingsKeyMode(sharedPreferences,
mInputMethodService);
postSetInputView(createInputView(mThemeIndex, true)); postSetInputView(createInputView(mThemeIndex, true));
} }
} }

View File

@ -118,8 +118,8 @@ public class Settings extends InputMethodSettingsActivity
public final boolean mBigramPredictionEnabled; public final boolean mBigramPredictionEnabled;
public final boolean mUseContactsDict; public final boolean mUseContactsDict;
private final boolean mVoiceButtonEnabled; private final boolean mVoiceKeyEnabled;
private final boolean mVoiceButtonOnPrimary; private final boolean mVoiceKeyOnMain;
public Values(final SharedPreferences prefs, final Context context, public Values(final SharedPreferences prefs, final Context context,
final String localeStr) { final String localeStr) {
@ -183,8 +183,8 @@ public class Settings extends InputMethodSettingsActivity
final String voiceModeMain = res.getString(R.string.voice_mode_main); final String voiceModeMain = res.getString(R.string.voice_mode_main);
final String voiceModeOff = res.getString(R.string.voice_mode_off); final String voiceModeOff = res.getString(R.string.voice_mode_off);
final String voiceMode = prefs.getString(PREF_VOICE_SETTINGS_KEY, voiceModeMain); final String voiceMode = prefs.getString(PREF_VOICE_SETTINGS_KEY, voiceModeMain);
mVoiceButtonEnabled = voiceMode != null && !voiceMode.equals(voiceModeOff); mVoiceKeyEnabled = voiceMode != null && !voiceMode.equals(voiceModeOff);
mVoiceButtonOnPrimary = voiceMode != null && voiceMode.equals(voiceModeMain); mVoiceKeyOnMain = voiceMode != null && voiceMode.equals(voiceModeMain);
Utils.setSystemLocale(res, savedLocale); Utils.setSystemLocale(res, savedLocale);
} }
@ -284,15 +284,15 @@ public class Settings extends InputMethodSettingsActivity
return builder.setIsPunctuationSuggestions().build(); return builder.setIsPunctuationSuggestions().build();
} }
public boolean isVoiceButtonEnabled(EditorInfo attribute) { public boolean isVoiceKeyEnabled(EditorInfo attribute) {
final boolean shortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled(); final boolean shortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled();
final int inputType = (attribute != null) ? attribute.inputType : 0; final int inputType = (attribute != null) ? attribute.inputType : 0;
return shortcutImeEnabled && mVoiceButtonEnabled return shortcutImeEnabled && mVoiceKeyEnabled
&& !InputTypeCompatUtils.isPasswordInputType(inputType); && !InputTypeCompatUtils.isPasswordInputType(inputType);
} }
public boolean isVoiceButtonOnPrimary() { public boolean isVoiceKeyOnMain() {
return mVoiceButtonOnPrimary; return mVoiceKeyOnMain;
} }
} }