Merge "Add "passwordInput" attribute to case tag of Keyboard"

This commit is contained in:
Tadashi G. Takaoka 2011-02-20 01:50:16 -08:00 committed by Android (Google) Code Review
commit a9f2fe2d59
9 changed files with 280 additions and 188 deletions

View file

@ -168,6 +168,7 @@
<enum name="web" value="4" /> <enum name="web" value="4" />
<enum name="phone" value="5" /> <enum name="phone" value="5" />
</attr> </attr>
<attr name="passwordInput" format="boolean" />
<attr name="hasSettingsKey" format="string" /> <attr name="hasSettingsKey" format="string" />
<attr name="voiceKeyEnabled" format="string" /> <attr name="voiceKeyEnabled" format="string" />
<attr name="hasVoiceKey" format="string" /> <attr name="hasVoiceKey" format="string" />

View file

@ -31,120 +31,189 @@
> >
<include <include
latin:keyboardLayout="@xml/kbd_key_styles" /> latin:keyboardLayout="@xml/kbd_key_styles" />
<!-- This row is intentionally not marked as a top row --> <switch>
<Row> <case
<Key latin:passwordInput="true"
latin:keyStyle="tabKeyStyle" >
latin:keyLabelOption="alignLeft" <!-- This row is intentionally not marked as a top row -->
latin:keyEdgeFlags="left" /> <Row>
<Spacer <Spacer
latin:horizontalGap="4.458%p" /> latin:horizontalGap="32.076%p" />
<Key
latin:keyLabel="-"
latin:keyWidth="8.042%p" />
<Key
latin:keyLabel="+"
latin:keyWidth="8.042%p" />
<Key
latin:keyLabel="."
latin:keyWidth="8.042%p" />
<Spacer
latin:horizontalGap="4.458%p" />
<Key
latin:keyLabel="1" />
<Key
latin:keyLabel="2" />
<Key
latin:keyLabel="3" />
<Spacer
latin:horizontalGap="9.360%p" />
<Key
latin:keyStyle="deleteKeyStyle"
latin:keyWidth="9.804%p"
latin:keyEdgeFlags="right" />
</Row>
<Row>
<Spacer
latin:horizontalGap="16.406%p" />
<Key
latin:keyLabel="*"
latin:keyWidth="8.042%p" />
<Key
latin:keyLabel="/"
latin:keyWidth="8.042%p" />
<Key
latin:keyLabel=","
latin:keyWidth="8.042%p" />
<Spacer
latin:horizontalGap="4.458%p" />
<Key
latin:keyLabel="4" />
<Key
latin:keyLabel="5" />
<Key
latin:keyLabel="6" />
<Spacer
latin:horizontalGap="4.458%p" />
<Key
latin:keyStyle="returnKeyStyle"
latin:keyWidth="14.706%p"
latin:keyEdgeFlags="right" />
</Row>
<Row>
<!-- There is an empty area bellow the "More" key and left of the "(" key. To ignore
the touch event on the area, "(" is intentionally not marked as a left edge key. -->
<Spacer
latin:horizontalGap="16.406%p" />
<Key
latin:keyLabel="("
latin:keyWidth="8.042%p" />
<Key
latin:keyLabel=")"
latin:keyWidth="8.042%p" />
<Key
latin:keyLabel="="
latin:keyWidth="8.042%p" />
<Spacer
latin:horizontalGap="4.458%p" />
<Key
latin:keyLabel="7" />
<Key
latin:keyLabel="8" />
<Key
latin:keyLabel="9" />
<!-- There is an empty area bellow the "Enter" key and right of the "9" key. To ignore
the touch event on the area, "9" is intentionally not marked as a right edge key. -->
</Row>
<!-- This row is intentionally not marked as a bottom row -->
<Row>
<!-- There is an empty area bellow the "More" key and left of the "space" key. To ignore
the touch event on the area, "space" is intentionally not marked as a left edge key. -->
<Spacer
latin:horizontalGap="8.362%p" />
<Key
latin:keyStyle="settingsKeyStyle"
latin:keyWidth="8.042%p" />
<Key
latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
latin:keyWidth="24.127%p" />
<Spacer
latin:horizontalGap="4.458%p" />
<Key
latin:keyLabel="*" />
<Key
latin:keyLabel="0" />
<Key
latin:keyLabel="#" />
<switch>
<case
latin:voiceKeyEnabled="true"
>
<Key <Key
latin:keyStyle="micKeyStyle" latin:keyLabel="1" />
<Key
latin:keyLabel="2" />
<Key
latin:keyLabel="3" />
<Spacer
latin:horizontalGap="22.272%p" />
<Key
latin:keyStyle="deleteKeyStyle"
latin:keyWidth="9.804%p"
latin:keyEdgeFlags="right" />
</Row>
<Row>
<Spacer
latin:horizontalGap="32.076%p" />
<Key
latin:keyLabel="4" />
<Key
latin:keyLabel="5" />
<Key
latin:keyLabel="6" />
<Spacer
latin:horizontalGap="17.371%p" />
<Key
latin:keyStyle="returnKeyStyle"
latin:keyWidth="14.706%p"
latin:keyEdgeFlags="right" />
</Row>
<Row>
<Spacer
latin:horizontalGap="32.076%p" />
<Key
latin:keyLabel="7" />
<Key
latin:keyLabel="8" />
<Key
latin:keyLabel="9" />
<!-- There is an empty area below the "Enter" key and right of the "9" key. To
ignore the touch event on the area, "9" is intentionally not marked as a right
edge key. -->
</Row>
<!-- This row is intentionally not marked as a bottom row -->
<Row>
<Spacer
latin:horizontalGap="44.026%p" />
<Key
latin:keyLabel="0" />
<!-- There is an empty area below the "Enter" key and right of the "#" key. To
ignore the touch event on the area, "#" is intentionally not marked as a right
edge key. -->
</Row>
</case>
<!-- latin:passwordInput="false" -->
<default>
<!-- This row is intentionally not marked as a top row -->
<Row>
<Key
latin:keyStyle="tabKeyStyle"
latin:keyLabelOption="alignLeft"
latin:keyEdgeFlags="left" />
<Spacer
latin:horizontalGap="4.458%p" />
<Key
latin:keyLabel="-"
latin:keyWidth="8.042%p" /> latin:keyWidth="8.042%p" />
</case> <Key
</switch> latin:keyLabel="+"
<!-- There is an empty area bellow the "Enter" key and right of the "#" key. To ignore latin:keyWidth="8.042%p" />
the touch event on the area, "#" is intentionally not marked as a right edge key. --> <Key
</Row> latin:keyLabel="."
latin:keyWidth="8.042%p" />
<Spacer
latin:horizontalGap="4.458%p" />
<Key
latin:keyLabel="1" />
<Key
latin:keyLabel="2" />
<Key
latin:keyLabel="3" />
<Spacer
latin:horizontalGap="9.360%p" />
<Key
latin:keyStyle="deleteKeyStyle"
latin:keyWidth="9.804%p"
latin:keyEdgeFlags="right" />
</Row>
<Row>
<Spacer
latin:horizontalGap="16.406%p" />
<Key
latin:keyLabel="*"
latin:keyWidth="8.042%p" />
<Key
latin:keyLabel="/"
latin:keyWidth="8.042%p" />
<Key
latin:keyLabel=","
latin:keyWidth="8.042%p" />
<Spacer
latin:horizontalGap="4.458%p" />
<Key
latin:keyLabel="4" />
<Key
latin:keyLabel="5" />
<Key
latin:keyLabel="6" />
<Spacer
latin:horizontalGap="4.458%p" />
<Key
latin:keyStyle="returnKeyStyle"
latin:keyWidth="14.706%p"
latin:keyEdgeFlags="right" />
</Row>
<Row>
<!-- There is an empty area below the "More" key and left of the "(" key. To
ignore the touch event on the area, "(" is intentionally not marked as a left
edge key. -->
<Spacer
latin:horizontalGap="16.406%p" />
<Key
latin:keyLabel="("
latin:keyWidth="8.042%p" />
<Key
latin:keyLabel=")"
latin:keyWidth="8.042%p" />
<Key
latin:keyLabel="="
latin:keyWidth="8.042%p" />
<Spacer
latin:horizontalGap="4.458%p" />
<Key
latin:keyLabel="7" />
<Key
latin:keyLabel="8" />
<Key
latin:keyLabel="9" />
<!-- There is an empty area below the "Enter" key and right of the "9" key. To
ignore the touch event on the area, "9" is intentionally not marked as a right
edge key. -->
</Row>
<!-- This row is intentionally not marked as a bottom row -->
<Row>
<!-- There is an empty area below the "More" key and left of the "space" key. To
ignore the touch event on the area, "space" is intentionally not marked as a
left edge key. -->
<Spacer
latin:horizontalGap="8.362%p" />
<Key
latin:keyStyle="settingsKeyStyle"
latin:keyWidth="8.042%p" />
<Key
latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
latin:keyWidth="24.127%p" />
<Spacer
latin:horizontalGap="4.458%p" />
<Key
latin:keyLabel="*" />
<Key
latin:keyLabel="0" />
<Key
latin:keyLabel="#" />
<switch>
<case
latin:voiceKeyEnabled="true"
>
<Key
latin:keyStyle="micKeyStyle"
latin:keyWidth="8.042%p" />
</case>
</switch>
<!-- There is an empty area below the "Enter" key and right of the "#" key. To
ignore the touch event on the area, "#" is intentionally not marked as a right
edge key. -->
</Row>
</default>
</switch>
</Keyboard> </Keyboard>

View file

@ -17,6 +17,7 @@
package com.android.inputmethod.keyboard; package com.android.inputmethod.keyboard;
import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.Utils;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
@ -41,6 +42,7 @@ public class KeyboardId {
public final int mMode; public final int mMode;
public final int mXmlId; public final int mXmlId;
public final int mColorScheme; public final int mColorScheme;
public final boolean mPasswordInput;
public final boolean mHasSettingsKey; public final boolean mHasSettingsKey;
public final boolean mVoiceKeyEnabled; public final boolean mVoiceKeyEnabled;
public final boolean mHasVoiceKey; public final boolean mHasVoiceKey;
@ -50,21 +52,25 @@ public class KeyboardId {
private final int mHashCode; private final int mHashCode;
public KeyboardId(String xmlName, int xmlId, Locale locale, int orientation, int mode, public KeyboardId(String xmlName, int xmlId, int colorScheme, Locale locale, int orientation,
int colorScheme, boolean hasSettingsKey, boolean voiceKeyEnabled, boolean hasVoiceKey, int mode, EditorInfo attribute, boolean hasSettingsKey, boolean voiceKeyEnabled,
int imeOptions, boolean enableShiftLock) { boolean hasVoiceKey, boolean enableShiftLock) {
final int inputType = (attribute != null) ? attribute.inputType : 0;
final int imeOptions = (attribute != null) ? attribute.imeOptions : 0;
this.mLocale = locale; this.mLocale = locale;
this.mOrientation = orientation; this.mOrientation = orientation;
this.mMode = mode; this.mMode = mode;
this.mXmlId = xmlId; this.mXmlId = xmlId;
this.mColorScheme = colorScheme; this.mColorScheme = colorScheme;
this.mPasswordInput = Utils.isPasswordInputType(inputType)
|| Utils.isVisiblePasswordInputType(inputType);
this.mHasSettingsKey = hasSettingsKey; this.mHasSettingsKey = hasSettingsKey;
this.mVoiceKeyEnabled = voiceKeyEnabled; this.mVoiceKeyEnabled = voiceKeyEnabled;
this.mHasVoiceKey = hasVoiceKey; this.mHasVoiceKey = hasVoiceKey;
// We are interested only in {@link EditorInfo#IME_MASK_ACTION} enum value and // We are interested only in {@link EditorInfo#IME_MASK_ACTION} enum value and
// {@link EditorInfo#IME_FLAG_NO_ENTER_ACTION}. // {@link EditorInfo#IME_FLAG_NO_ENTER_ACTION}.
this.mImeAction = imeOptions this.mImeAction = imeOptions & (
& (EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION); EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION);
this.mEnableShiftLock = enableShiftLock; this.mEnableShiftLock = enableShiftLock;
this.mXmlName = xmlName; this.mXmlName = xmlName;
@ -74,6 +80,7 @@ public class KeyboardId {
mode, mode,
xmlId, xmlId,
colorScheme, colorScheme,
mPasswordInput,
hasSettingsKey, hasSettingsKey,
voiceKeyEnabled, voiceKeyEnabled,
hasVoiceKey, hasVoiceKey,
@ -113,6 +120,7 @@ public class KeyboardId {
&& other.mMode == this.mMode && other.mMode == this.mMode
&& other.mXmlId == this.mXmlId && other.mXmlId == this.mXmlId
&& other.mColorScheme == this.mColorScheme && other.mColorScheme == this.mColorScheme
&& other.mPasswordInput == this.mPasswordInput
&& other.mHasSettingsKey == this.mHasSettingsKey && other.mHasSettingsKey == this.mHasSettingsKey
&& other.mVoiceKeyEnabled == this.mVoiceKeyEnabled && other.mVoiceKeyEnabled == this.mVoiceKeyEnabled
&& other.mHasVoiceKey == this.mHasVoiceKey && other.mHasVoiceKey == this.mHasVoiceKey
@ -127,17 +135,19 @@ public class KeyboardId {
@Override @Override
public String toString() { public String toString() {
return String.format("[%s.xml %s %s %s imeOptions=%s %s%s%s%s%s]", return String.format("[%s.xml %s %s %s imeAction=%s %s%s%s%s%s%s]",
mXmlName, mXmlName,
mLocale, mLocale,
(mOrientation == 1 ? "port" : "land"), (mOrientation == 1 ? "port" : "land"),
modeName(mMode), modeName(mMode),
imeOptionsName(mImeAction), imeOptionsName(mImeAction),
colorSchemeName(mColorScheme), (mPasswordInput ? " passwordInput" : ""),
(mHasSettingsKey ? " hasSettingsKey" : ""), (mHasSettingsKey ? " hasSettingsKey" : ""),
(mVoiceKeyEnabled ? " voiceKeyEnabled" : ""), (mVoiceKeyEnabled ? " voiceKeyEnabled" : ""),
(mHasVoiceKey ? " hasVoiceKey" : ""), (mHasVoiceKey ? " hasVoiceKey" : ""),
(mEnableShiftLock ? " enableShiftLock" : "")); (mEnableShiftLock ? " enableShiftLock" : ""),
colorSchemeName(mColorScheme)
);
} }
public static String modeName(int mode) { public static String modeName(int mode) {

View file

@ -419,6 +419,8 @@ public class KeyboardParser {
try { try {
final boolean modeMatched = matchInteger(a, final boolean modeMatched = matchInteger(a,
R.styleable.Keyboard_Case_mode, id.mMode); R.styleable.Keyboard_Case_mode, id.mMode);
final boolean passwordInputMatched = matchBoolean(a,
R.styleable.Keyboard_Case_passwordInput, id.mPasswordInput);
final boolean settingsKeyMatched = matchBoolean(a, final boolean settingsKeyMatched = matchBoolean(a,
R.styleable.Keyboard_Case_hasSettingsKey, id.mHasSettingsKey); R.styleable.Keyboard_Case_hasSettingsKey, id.mHasSettingsKey);
final boolean voiceEnabledMatched = matchBoolean(a, final boolean voiceEnabledMatched = matchBoolean(a,
@ -435,15 +437,16 @@ public class KeyboardParser {
R.styleable.Keyboard_Case_imeAction, id.mImeAction); R.styleable.Keyboard_Case_imeAction, id.mImeAction);
final boolean languageCodeMatched = matchString(a, final boolean languageCodeMatched = matchString(a,
R.styleable.Keyboard_Case_languageCode, id.mLocale.getLanguage()); R.styleable.Keyboard_Case_languageCode, id.mLocale.getLanguage());
final boolean selected = modeMatched && settingsKeyMatched && voiceEnabledMatched final boolean selected = modeMatched && passwordInputMatched && settingsKeyMatched
&& voiceKeyMatched && colorSchemeMatched && imeActionMatched && voiceEnabledMatched && voiceKeyMatched && colorSchemeMatched
&& languageCodeMatched; && imeActionMatched && languageCodeMatched;
if (DEBUG) Log.d(TAG, String.format("<%s%s%s%s%s%s%s%s> %s", TAG_CASE, if (DEBUG) Log.d(TAG, String.format("<%s%s%s%s%s%s%s%s%s> %s", TAG_CASE,
textAttr(KeyboardId.modeName( textAttr(KeyboardId.modeName(
a.getInt(R.styleable.Keyboard_Case_mode, -1)), "mode"), a.getInt(R.styleable.Keyboard_Case_mode, -1)), "mode"),
textAttr(KeyboardId.colorSchemeName( textAttr(KeyboardId.colorSchemeName(
a.getInt(R.styleable.KeyboardView_colorScheme, -1)), "colorSchemeName"), a.getInt(R.styleable.KeyboardView_colorScheme, -1)), "colorSchemeName"),
booleanAttr(a, R.styleable.Keyboard_Case_passwordInput, "passwordInput"),
booleanAttr(a, R.styleable.Keyboard_Case_hasSettingsKey, "hasSettingsKey"), booleanAttr(a, R.styleable.Keyboard_Case_hasSettingsKey, "hasSettingsKey"),
booleanAttr(a, R.styleable.Keyboard_Case_voiceKeyEnabled, "voiceKeyEnabled"), booleanAttr(a, R.styleable.Keyboard_Case_voiceKeyEnabled, "voiceKeyEnabled"),
booleanAttr(a, R.styleable.Keyboard_Case_hasVoiceKey, "hasVoiceKey"), booleanAttr(a, R.styleable.Keyboard_Case_hasVoiceKey, "hasVoiceKey"),

View file

@ -28,6 +28,7 @@ import android.content.SharedPreferences;
import android.content.res.Resources; import android.content.res.Resources;
import android.util.Log; import android.util.Log;
import android.view.InflateException; import android.view.InflateException;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import java.lang.ref.SoftReference; import java.lang.ref.SoftReference;
@ -66,8 +67,9 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache = private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache =
new HashMap<KeyboardId, SoftReference<LatinKeyboard>>(); new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
// TODO: clean mMode up and use mAttribute instead.
private int mMode = KeyboardId.MODE_TEXT; /* default value */ private int mMode = KeyboardId.MODE_TEXT; /* default value */
private int mImeOptions; private EditorInfo mAttribute;
private boolean mIsSymbols; 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. */
@ -128,10 +130,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
final int orientation = res.getConfiguration().orientation; final int orientation = res.getConfiguration().orientation;
final int mode = mMode; final int mode = mMode;
final int colorScheme = getColorScheme(); final int colorScheme = getColorScheme();
final boolean hasSettingsKey = mHasSettingsKey; final boolean hasVoiceKey = mVoiceKeyEnabled && !mVoiceButtonOnPrimary;
final boolean voiceKeyEnabled = mVoiceKeyEnabled;
final boolean hasVoiceKey = voiceKeyEnabled && !mVoiceButtonOnPrimary;
final int imeOptions = mImeOptions;
// Note: This comment is only applied for phone number keyboard layout. // 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 // 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, // between "phone keyboard" and "phone symbols keyboard". But on xlarge device,
@ -140,26 +139,25 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
// mSymbolsId and mSymbolsShiftedId to "phone keyboard" and "phone symbols keyboard" // mSymbolsId and mSymbolsShiftedId to "phone keyboard" and "phone symbols keyboard"
// respectively here for xlarge device's layout switching. // respectively here for xlarge device's layout switching.
int xmlId = mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone : R.xml.kbd_symbols; int xmlId = mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone : R.xml.kbd_symbols;
mSymbolsId = new KeyboardId( final String xmlName = res.getResourceEntryName(xmlId);
res.getResourceEntryName(xmlId), xmlId, locale, orientation, mode, colorScheme, mSymbolsId = new KeyboardId(xmlName, xmlId, colorScheme, locale, orientation, mode,
hasSettingsKey, voiceKeyEnabled, hasVoiceKey, imeOptions, true); mAttribute, mHasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, true);
xmlId = mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone_symbols : R.xml.kbd_symbols_shift; xmlId = mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone_symbols : R.xml.kbd_symbols_shift;
mSymbolsShiftedId = new KeyboardId( mSymbolsShiftedId = new KeyboardId(xmlName, xmlId, colorScheme, locale, orientation, mode,
res.getResourceEntryName(xmlId), xmlId, locale, orientation, mode, colorScheme, mAttribute, mHasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, true);
hasSettingsKey, voiceKeyEnabled, hasVoiceKey, imeOptions, true);
} }
private boolean hasVoiceKey(boolean isSymbols) { private boolean hasVoiceKey(boolean isSymbols) {
return mVoiceKeyEnabled && (isSymbols != mVoiceButtonOnPrimary); return mVoiceKeyEnabled && (isSymbols != mVoiceButtonOnPrimary);
} }
public void loadKeyboard(int mode, int imeOptions, boolean voiceKeyEnabled, public void loadKeyboard(int mode, EditorInfo attribute, boolean voiceKeyEnabled,
boolean voiceButtonOnPrimary) { boolean voiceButtonOnPrimary) {
mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA; mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA;
try { try {
if (mInputView == null) return; if (mInputView == null) return;
final Keyboard oldKeyboard = mInputView.getKeyboard(); final Keyboard oldKeyboard = mInputView.getKeyboard();
loadKeyboardInternal(mode, imeOptions, voiceKeyEnabled, voiceButtonOnPrimary, false); loadKeyboardInternal(mode, attribute, voiceKeyEnabled, voiceButtonOnPrimary, false);
final Keyboard newKeyboard = mInputView.getKeyboard(); final Keyboard newKeyboard = mInputView.getKeyboard();
if (newKeyboard.isAlphaKeyboard()) { if (newKeyboard.isAlphaKeyboard()) {
final boolean localeChanged = (oldKeyboard == null) final boolean localeChanged = (oldKeyboard == null)
@ -167,23 +165,25 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged); mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged);
} }
} catch (RuntimeException e) { } catch (RuntimeException e) {
Log.w(TAG, e); // Get KeyboardId to record which keyboard has been failed to load.
LatinImeLogger.logOnException(mode + "," + imeOptions, e); final KeyboardId id = getKeyboardId(mode, attribute, false);
Log.w(TAG, "loading keyboard failed: " + id, e);
LatinImeLogger.logOnException(id.toString(), e);
} }
} }
private void loadKeyboardInternal(int mode, int imeOptions, boolean voiceButtonEnabled, private void loadKeyboardInternal(int mode, EditorInfo attribute, boolean voiceButtonEnabled,
boolean voiceButtonOnPrimary, boolean isSymbols) { boolean voiceButtonOnPrimary, boolean isSymbols) {
if (mInputView == null) return; if (mInputView == null) return;
mMode = mode; mMode = mode;
mImeOptions = imeOptions; mAttribute = attribute;
mVoiceKeyEnabled = voiceButtonEnabled; mVoiceKeyEnabled = voiceButtonEnabled;
mVoiceButtonOnPrimary = voiceButtonOnPrimary; mVoiceButtonOnPrimary = voiceButtonOnPrimary;
mIsSymbols = isSymbols; mIsSymbols = isSymbols;
// Update the settings key state because number of enabled IMEs could have been changed // Update the settings key state because number of enabled IMEs could have been changed
mHasSettingsKey = getSettingsKeyMode(mPrefs, mInputMethodService); mHasSettingsKey = getSettingsKeyMode(mPrefs, mInputMethodService);
final KeyboardId id = getKeyboardId(mode, imeOptions, isSymbols); final KeyboardId id = getKeyboardId(mode, attribute, isSymbols);
final Keyboard oldKeyboard = mInputView.getKeyboard(); final Keyboard oldKeyboard = mInputView.getKeyboard();
if (oldKeyboard != null && oldKeyboard.mId.equals(id)) if (oldKeyboard != null && oldKeyboard.mId.equals(id))
@ -228,7 +228,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
return keyboard; return keyboard;
} }
private KeyboardId getKeyboardId(int mode, int imeOptions, boolean isSymbols) { private KeyboardId getKeyboardId(int mode, EditorInfo attribute, boolean isSymbols) {
final boolean hasVoiceKey = hasVoiceKey(isSymbols); final boolean hasVoiceKey = hasVoiceKey(isSymbols);
final int charColorId = getColorScheme(); final int charColorId = getColorScheme();
final int xmlId; final int xmlId;
@ -260,8 +260,8 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
final int orientation = res.getConfiguration().orientation; final int orientation = res.getConfiguration().orientation;
final Locale locale = mSubtypeSwitcher.getInputLocale(); final Locale locale = mSubtypeSwitcher.getInputLocale();
return new KeyboardId( return new KeyboardId(
res.getResourceEntryName(xmlId), xmlId, locale, orientation, mode, charColorId, res.getResourceEntryName(xmlId), xmlId, charColorId, locale, orientation, mode,
mHasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, imeOptions, enableShiftLock); attribute, mHasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, enableShiftLock);
} }
public int getKeyboardMode() { public int getKeyboardMode() {
@ -566,7 +566,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
} }
private void toggleKeyboardMode() { private void toggleKeyboardMode() {
loadKeyboardInternal(mMode, mImeOptions, mVoiceKeyEnabled, mVoiceButtonOnPrimary, loadKeyboardInternal(mMode, mAttribute, mVoiceKeyEnabled, mVoiceButtonOnPrimary,
!mIsSymbols); !mIsSymbols);
if (mIsSymbols) { if (mIsSymbols) {
mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN; mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN;

View file

@ -155,6 +155,8 @@ public class LatinKeyboard extends Keyboard {
} }
private void updateSpacebarForLocale(boolean isAutoCorrection) { private void updateSpacebarForLocale(boolean isAutoCorrection) {
if (mSpaceKey == null)
return;
final Resources res = mContext.getResources(); final Resources res = mContext.getResources();
// If application locales are explicitly selected. // If application locales are explicitly selected.
if (SubtypeSwitcher.getInstance().needsToDisplayLanguage()) { if (SubtypeSwitcher.getInstance().needsToDisplayLanguage()) {

View file

@ -494,26 +494,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return container; return container;
} }
// Please refer to TextView.isPasswordInputType
private static boolean isPasswordInputType(int inputType) {
final int variation =
inputType & (InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION);
return (variation
== (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD))
|| (variation
== (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD))
|| (variation
== (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD));
}
// Please refer to TextView.isVisiblePasswordInputType
private static boolean isVisiblePasswordInputType(int inputType) {
final int variation =
inputType & (InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION);
return variation
== (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
}
private static boolean isEmailVariation(int variation) { private static boolean isEmailVariation(int variation) {
return variation == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS return variation == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
|| variation == InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS; || variation == InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS;
@ -539,10 +519,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Most such things we decide below in initializeInputAttributesAndGetMode, but we need to // Most such things we decide below in initializeInputAttributesAndGetMode, but we need to
// know now whether this is a password text field, because we need to know now whether we // know now whether this is a password text field, because we need to know now whether we
// want to enable the voice button. // want to enable the voice button.
mVoiceConnector.resetVoiceStates(isPasswordInputType(attribute.inputType) mVoiceConnector.resetVoiceStates(Utils.isPasswordInputType(attribute.inputType)
|| isVisiblePasswordInputType(attribute.inputType)); || Utils.isVisiblePasswordInputType(attribute.inputType));
final int mode = initializeInputAttributesAndGetMode(attribute.inputType); final int mode = initializeInputAttributesAndGetMode(attribute);
inputView.closing(); inputView.closing();
mEnteredText = null; mEnteredText = null;
@ -553,7 +533,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
loadSettings(attribute); loadSettings(attribute);
if (mSubtypeSwitcher.isKeyboardMode()) { if (mSubtypeSwitcher.isKeyboardMode()) {
switcher.loadKeyboard(mode, attribute.imeOptions, switcher.loadKeyboard(mode, attribute,
mVoiceConnector.isVoiceButtonEnabled(), mVoiceConnector.isVoiceButtonEnabled(),
mVoiceConnector.isVoiceButtonOnPrimary()); mVoiceConnector.isVoiceButtonOnPrimary());
switcher.updateShiftState(); switcher.updateShiftState();
@ -577,7 +557,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
} }
private int initializeInputAttributesAndGetMode(int inputType) { // TODO: Separate calculating keyboard mode from initializing attributes, and make it an
// utility method in {@link Utils}.
private int initializeInputAttributesAndGetMode(EditorInfo attribute) {
if (attribute == null) return KeyboardId.MODE_TEXT;
final int inputType = attribute.inputType;
final int variation = inputType & InputType.TYPE_MASK_VARIATION; final int variation = inputType & InputType.TYPE_MASK_VARIATION;
mAutoSpace = false; mAutoSpace = false;
mInputTypeNoAutoCorrect = false; mInputTypeNoAutoCorrect = false;
@ -597,16 +581,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
case InputType.TYPE_CLASS_TEXT: case InputType.TYPE_CLASS_TEXT:
mIsSettingsSuggestionStripOn = true; mIsSettingsSuggestionStripOn = true;
// Make sure that passwords are not displayed in candidate view // Make sure that passwords are not displayed in candidate view
if (isPasswordInputType(inputType) || isVisiblePasswordInputType(inputType)) { if (Utils.isPasswordInputType(inputType)
|| Utils.isVisiblePasswordInputType(inputType)) {
mIsSettingsSuggestionStripOn = false; mIsSettingsSuggestionStripOn = false;
} }
if (isEmailVariation(variation) if (LatinIME.isEmailVariation(variation)
|| variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) { || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) {
mAutoSpace = false; mAutoSpace = false;
} else { } else {
mAutoSpace = true; mAutoSpace = true;
} }
if (isEmailVariation(variation)) { if (LatinIME.isEmailVariation(variation)) {
mIsSettingsSuggestionStripOn = false; mIsSettingsSuggestionStripOn = false;
mode = KeyboardId.MODE_EMAIL; mode = KeyboardId.MODE_EMAIL;
} else if (variation == InputType.TYPE_TEXT_VARIATION_URI) { } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) {
@ -1924,15 +1909,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mSubtypeSwitcher.toggleLanguage(reset, next); mSubtypeSwitcher.toggleLanguage(reset, next);
} }
// Reload keyboard because the current language has been changed. // Reload keyboard because the current language has been changed.
KeyboardSwitcher switcher = mKeyboardSwitcher;
final EditorInfo attribute = getCurrentInputEditorInfo(); final EditorInfo attribute = getCurrentInputEditorInfo();
final int mode = initializeInputAttributesAndGetMode((attribute != null) final int mode = initializeInputAttributesAndGetMode(attribute);
? attribute.inputType : 0); mKeyboardSwitcher.loadKeyboard(mode, attribute,
final int imeOptions = (attribute != null) ? attribute.imeOptions : 0; mVoiceConnector.isVoiceButtonEnabled(), mVoiceConnector.isVoiceButtonOnPrimary());
switcher.loadKeyboard(mode, imeOptions, mVoiceConnector.isVoiceButtonEnabled(),
mVoiceConnector.isVoiceButtonOnPrimary());
initSuggest(); initSuggest();
switcher.updateShiftState(); mKeyboardSwitcher.updateShiftState();
} }
@Override @Override

View file

@ -16,13 +16,17 @@
package com.android.inputmethod.latin; package com.android.inputmethod.latin;
import com.android.inputmethod.keyboard.KeyboardId;
import android.inputmethodservice.InputMethodService; import android.inputmethodservice.InputMethodService;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.os.Process; import android.os.Process;
import android.text.InputType;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.util.Log; import android.util.Log;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
@ -55,7 +59,7 @@ public class Utils {
} }
public static class GCUtils { public static class GCUtils {
private static final String TAG = "GCUtils"; private static final String GC_TAG = GCUtils.class.getSimpleName();
public static final int GC_TRY_COUNT = 2; public static final int GC_TRY_COUNT = 2;
// GC_TRY_LOOP_MAX is used for the hard limit of GC wait, // GC_TRY_LOOP_MAX is used for the hard limit of GC wait,
// GC_TRY_LOOP_MAX should be greater than GC_TRY_COUNT. // GC_TRY_LOOP_MAX should be greater than GC_TRY_COUNT.
@ -84,7 +88,7 @@ public class Utils {
Thread.sleep(GC_INTERVAL); Thread.sleep(GC_INTERVAL);
return true; return true;
} catch (InterruptedException e) { } catch (InterruptedException e) {
Log.e(TAG, "Sleep was interrupted."); Log.e(GC_TAG, "Sleep was interrupted.");
LatinImeLogger.logOnException(metaData, t); LatinImeLogger.logOnException(metaData, t);
return false; return false;
} }
@ -452,4 +456,24 @@ public class Utils {
return new PrintWriter(new FileOutputStream(mFile), true /* autoFlush */); return new PrintWriter(new FileOutputStream(mFile), true /* autoFlush */);
} }
} }
// Please refer to TextView.isPasswordInputType
public static boolean isPasswordInputType(int inputType) {
final int variation =
inputType & (InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION);
return (variation
== (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD))
|| (variation
== (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD))
|| (variation
== (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD));
}
// Please refer to TextView.isVisiblePasswordInputType
public static boolean isVisiblePasswordInputType(int inputType) {
final int variation =
inputType & (InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION);
return variation
== (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
}
} }

View file

@ -23,6 +23,7 @@ import android.content.res.AssetFileDescriptor;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.test.AndroidTestCase; import android.test.AndroidTestCase;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.inputmethod.EditorInfo;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
@ -30,9 +31,9 @@ import java.util.Locale;
public class SuggestTestsBase extends AndroidTestCase { public class SuggestTestsBase extends AndroidTestCase {
protected static final KeyboardId US_KEYBOARD_ID = new KeyboardId("en_US qwerty keyboard", protected static final KeyboardId US_KEYBOARD_ID = new KeyboardId("en_US qwerty keyboard",
com.android.inputmethod.latin.R.xml.kbd_qwerty, Locale.US, com.android.inputmethod.latin.R.xml.kbd_qwerty, KeyboardView.COLOR_SCHEME_WHITE,
Configuration.ORIENTATION_LANDSCAPE, KeyboardId.MODE_TEXT, Locale.US, Configuration.ORIENTATION_LANDSCAPE, KeyboardId.MODE_TEXT,
KeyboardView.COLOR_SCHEME_WHITE, false, false, false, 0, false); new EditorInfo(), false, false, false, false);
protected File mTestPackageFile; protected File mTestPackageFile;