aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com')
-rw-r--r--java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/Key.java17
-rw-r--r--java/src/com/android/inputmethod/keyboard/Keyboard.java16
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardId.java225
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSet.java148
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java17
-rw-r--r--java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java19
-rw-r--r--java/src/com/android/inputmethod/keyboard/MiniKeyboard.java2
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java20
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java132
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/XmlParseUtils.java77
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java63
-rw-r--r--java/src/com/android/inputmethod/latin/LatinImeLogger.java12
-rw-r--r--java/src/com/android/inputmethod/latin/MoreSuggestions.java2
-rw-r--r--java/src/com/android/inputmethod/latin/UserBigramDictionary.java2
-rw-r--r--java/src/com/android/inputmethod/latin/UserUnigramDictionary.java2
-rw-r--r--java/src/com/android/inputmethod/latin/WordComposer.java2
17 files changed, 476 insertions, 286 deletions
diff --git a/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java b/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java
index dbe7aec6a..e75e14861 100644
--- a/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java
+++ b/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java
@@ -17,7 +17,7 @@
package com.android.inputmethod.deprecated.languageswitcher;
import com.android.inputmethod.compat.SharedPreferencesCompat;
-import com.android.inputmethod.keyboard.internal.KeyboardBuilder;
+import com.android.inputmethod.keyboard.KeyboardSet;
import com.android.inputmethod.latin.DictionaryFactory;
import com.android.inputmethod.latin.LocaleUtils;
import com.android.inputmethod.latin.R;
@@ -162,8 +162,8 @@ public class InputLanguageSelection extends PreferenceActivity {
try {
final String localeStr = locale.toString();
- final String[] layoutCountryCodes = KeyboardBuilder.parseKeyboardLocale(
- this, R.xml.kbd_qwerty).split(",", -1);
+ final String[] layoutCountryCodes = KeyboardSet.parseKeyboardLocale(
+ getResources(), R.xml.keyboard_set).split(",", -1);
if (!TextUtils.isEmpty(localeStr) && layoutCountryCodes.length > 0) {
for (String s : layoutCountryCodes) {
if (s.equals(localeStr)) {
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index ced763841..4e4ccef18 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -28,13 +28,14 @@ import android.util.Xml;
import com.android.inputmethod.keyboard.internal.KeyStyles;
import com.android.inputmethod.keyboard.internal.KeyStyles.KeyStyle;
import com.android.inputmethod.keyboard.internal.KeyboardBuilder;
-import com.android.inputmethod.keyboard.internal.KeyboardBuilder.ParseException;
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
import com.android.inputmethod.keyboard.internal.KeyboardParams;
import com.android.inputmethod.keyboard.internal.MoreKeySpecParser;
+import com.android.inputmethod.keyboard.internal.XmlParseUtils;
import com.android.inputmethod.latin.R;
import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
import java.util.HashMap;
import java.util.Map;
@@ -212,9 +213,10 @@ public class Key {
* this key.
* @param parser the XML parser containing the attributes for this key
* @param keyStyles active key styles set
+ * @throws XmlPullParserException
*/
public Key(Resources res, KeyboardParams params, KeyboardBuilder.Row row,
- XmlPullParser parser, KeyStyles keyStyles) {
+ XmlPullParser parser, KeyStyles keyStyles) throws XmlPullParserException {
final float horizontalGap = isSpacer() ? 0 : params.mHorizontalGap;
final int keyHeight = row.mRowHeight;
mVerticalGap = params.mVerticalGap;
@@ -228,7 +230,8 @@ public class Key {
String styleName = keyAttr.getString(R.styleable.Keyboard_Key_keyStyle);
style = keyStyles.getKeyStyle(styleName);
if (style == null)
- throw new ParseException("Unknown key style: " + styleName, parser);
+ throw new XmlParseUtils.ParseException(
+ "Unknown key style: " + styleName, parser);
} else {
style = KeyStyles.getEmptyKeyStyle();
}
@@ -468,9 +471,9 @@ public class Key {
* Detects if a point falls on this key.
* @param x the x-coordinate of the point
* @param y the y-coordinate of the point
- * @return whether or not the point falls on the key. If the key is attached to an edge, it will
- * assume that all points between the key and the edge are considered to be on the key.
- * @see {@link #markAsLeftEdge(KeyboardParams)} etc.
+ * @return whether or not the point falls on the key. If the key is attached to an edge, it
+ * will assume that all points between the key and the edge are considered to be on the key.
+ * @see #markAsLeftEdge(KeyboardParams) etc.
*/
public boolean isOnKey(int x, int y) {
return mHitBox.contains(x, y);
@@ -569,7 +572,7 @@ public class Key {
public static class Spacer extends Key {
public Spacer(Resources res, KeyboardParams params, KeyboardBuilder.Row row,
- XmlPullParser parser, KeyStyles keyStyles) {
+ XmlPullParser parser, KeyStyles keyStyles) throws XmlPullParserException {
super(res, params, row, parser, keyStyles);
}
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index e267aa65c..814b52398 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -151,6 +151,9 @@ public class Keyboard {
}
public Key getKey(int code) {
+ if (code == CODE_DUMMY) {
+ return null;
+ }
final Integer keyCode = code;
if (mKeyCache.containsKey(keyCode)) {
return mKeyCache.get(keyCode);
@@ -232,19 +235,6 @@ public class Keyboard {
return mProximityInfo.getNearestKeys(x, y);
}
- public static String themeName(int themeId) {
- // This should be aligned with theme-*.xml resource files' themeId attribute.
- switch (themeId) {
- case 0: return "Basic";
- case 1: return "BasicHighContrast";
- case 5: return "IceCreamSandwich";
- case 6: return "Stone";
- case 7: return "StoneBold";
- case 8: return "GingerBread";
- default: return null;
- }
- }
-
public static String printableCode(int code) {
switch (code) {
case CODE_SHIFT: return "shift";
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
index ecc821a4b..3b3ff0709 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
@@ -21,11 +21,11 @@ import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.compat.EditorInfoCompatUtils;
import com.android.inputmethod.compat.InputTypeCompatUtils;
-import com.android.inputmethod.latin.R;
import java.util.Arrays;
import java.util.Locale;
+// TODO: Move to com.android.inputmethod.keyboard.internal package.
/**
* Represents the parameters necessary to construct a new LatinKeyboard,
* which also serve as a unique identifier for each keyboard type.
@@ -38,100 +38,167 @@ public class KeyboardId {
public static final int MODE_PHONE = 4;
public static final int MODE_NUMBER = 5;
- public static final int F2KEY_MODE_NONE = 0;
- public static final int F2KEY_MODE_SETTINGS = 1;
- public static final int F2KEY_MODE_SHORTCUT_IME = 2;
- public static final int F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS = 3;
+ public static final int ELEMENT_ALPHABET = 0;
+ /* TODO: Implement alphabet variant shift keyboard.
+ public static final int ELEMENT_ALPHABET_MANUAL_TEMPORARY_SHIFT = 1;
+ public static final int ELEMENT_ALPHABET_AUTOMATIC_TEMPORARY_SHIFT = 2;
+ public static final int ELEMENT_ALPHABET_SHIFT_LOCK = 3;
+ public static final int ELEMENT_ALPHABET_SHIFT_LOCK_SHIFT = 4;
+ */
+ public static final int ELEMENT_SYMBOLS = 5;
+ public static final int ELEMENT_SYMBOLS_SHIFT = 6;
+ public static final int ELEMENT_PHONE = 7;
+ public static final int ELEMENT_PHONE_SHIFT = 8;
+ public static final int ELEMENT_NUMBER = 9;
+
+ private static final int F2KEY_MODE_NONE = 0;
+ private static final int F2KEY_MODE_SETTINGS = 1;
+ private static final int F2KEY_MODE_SHORTCUT_IME = 2;
+ private static final int F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS = 3;
public final Locale mLocale;
public final int mOrientation;
public final int mWidth;
public final int mMode;
- public final int mXmlId;
- public final boolean mNavigateAction;
- public final boolean mPasswordInput;
- // TODO: Clean up these booleans and modes.
- public final boolean mHasSettingsKey;
- public final int mF2KeyMode;
+ // TODO: Remove this field.
+ private final int mXmlId;
+ public final int mElementState;
+ private final int mInputType;
+ private final int mImeOptions;
+ private final boolean mSettingsKeyEnabled;
public final boolean mClobberSettingsKey;
public final boolean mShortcutKeyEnabled;
public final boolean mHasShortcutKey;
- public final int mImeAction;
-
- public final String mXmlName;
- public final EditorInfo mEditorInfo;
private final int mHashCode;
- public KeyboardId(String xmlName, int xmlId, Locale locale, int orientation, int width,
- int mode, EditorInfo editorInfo, boolean hasSettingsKey, int f2KeyMode,
+ public KeyboardId(int xmlId, int elementState, Locale locale, int orientation, int width,
+ int mode, EditorInfo editorInfo, boolean settingsKeyEnabled,
+ boolean clobberSettingsKey, boolean shortcutKeyEnabled, boolean hasShortcutKey) {
+ this(xmlId, elementState, locale, orientation, width, mode,
+ (editorInfo != null ? editorInfo.inputType : 0),
+ (editorInfo != null ? editorInfo.imeOptions : 0),
+ settingsKeyEnabled, clobberSettingsKey, shortcutKeyEnabled, hasShortcutKey);
+ }
+
+ private KeyboardId(int xmlId, int elementState, Locale locale, int orientation, int width,
+ int mode, int inputType, int imeOptions, boolean settingsKeyEnabled,
boolean clobberSettingsKey, boolean shortcutKeyEnabled, boolean hasShortcutKey) {
- final int inputType = (editorInfo != null) ? editorInfo.inputType : 0;
- final int imeOptions = (editorInfo != null) ? editorInfo.imeOptions : 0;
this.mLocale = locale;
this.mOrientation = orientation;
this.mWidth = width;
this.mMode = mode;
this.mXmlId = xmlId;
- // Note: Turn off checking navigation flag to show TAB key for now.
- this.mNavigateAction = InputTypeCompatUtils.isWebInputType(inputType);
-// || EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions)
-// || EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions);
- this.mPasswordInput = InputTypeCompatUtils.isPasswordInputType(inputType)
- || InputTypeCompatUtils.isVisiblePasswordInputType(inputType);
- this.mHasSettingsKey = hasSettingsKey;
- this.mF2KeyMode = f2KeyMode;
+ this.mElementState = elementState;
+ this.mInputType = inputType;
+ this.mImeOptions = imeOptions;
+ this.mSettingsKeyEnabled = settingsKeyEnabled;
this.mClobberSettingsKey = clobberSettingsKey;
this.mShortcutKeyEnabled = shortcutKeyEnabled;
this.mHasShortcutKey = hasShortcutKey;
- // We are interested only in {@link EditorInfo#IME_MASK_ACTION} enum value and
- // {@link EditorInfo#IME_FLAG_NO_ENTER_ACTION}.
- this.mImeAction = imeOptions & (
- EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION);
- this.mXmlName = xmlName;
- this.mEditorInfo = editorInfo;
-
- this.mHashCode = Arrays.hashCode(new Object[] {
- locale,
- orientation,
- width,
- mode,
- xmlId,
- mNavigateAction,
- mPasswordInput,
- hasSettingsKey,
- f2KeyMode,
- clobberSettingsKey,
- shortcutKeyEnabled,
- hasShortcutKey,
- mImeAction,
+ this.mHashCode = hashCode(this);
+ }
+
+ private static int hashCode(KeyboardId id) {
+ return Arrays.hashCode(new Object[] {
+ id.mOrientation,
+ id.mElementState,
+ id.mMode,
+ id.mWidth,
+ id.mXmlId,
+ id.navigateAction(),
+ id.passwordInput(),
+ id.mSettingsKeyEnabled,
+ id.mClobberSettingsKey,
+ id.mShortcutKeyEnabled,
+ id.mHasShortcutKey,
+ id.imeAction(),
+ id.mLocale
});
}
- public KeyboardId cloneWithNewXml(String xmlName, int xmlId) {
- return new KeyboardId(xmlName, xmlId, mLocale, mOrientation, mWidth, mMode, mEditorInfo,
- false, F2KEY_MODE_NONE, false, false, false);
+ private boolean equals(KeyboardId other) {
+ if (other == this)
+ return true;
+ return other.mOrientation == this.mOrientation
+ && other.mElementState == this.mElementState
+ && other.mMode == this.mMode
+ && other.mWidth == this.mWidth
+ && other.mXmlId == this.mXmlId
+ && other.navigateAction() == this.navigateAction()
+ && other.passwordInput() == this.passwordInput()
+ && other.mSettingsKeyEnabled == this.mSettingsKeyEnabled
+ && other.mClobberSettingsKey == this.mClobberSettingsKey
+ && other.mShortcutKeyEnabled == this.mShortcutKeyEnabled
+ && other.mHasShortcutKey == this.mHasShortcutKey
+ && other.imeAction() == this.imeAction()
+ && other.mLocale.equals(this.mLocale);
}
+ public KeyboardId cloneWithNewXml(int xmlId) {
+ return new KeyboardId(xmlId, mElementState, mLocale, mOrientation, mWidth, mMode,
+ mInputType, mImeOptions, false, false, false, false);
+ }
+
+ // Remove this method.
public int getXmlId() {
return mXmlId;
}
public boolean isAlphabetKeyboard() {
- return mXmlId == R.xml.kbd_qwerty;
+ return mElementState < ELEMENT_SYMBOLS;
}
public boolean isSymbolsKeyboard() {
- return mXmlId == R.xml.kbd_symbols || mXmlId == R.xml.kbd_symbols_shift;
+ return mElementState == ELEMENT_SYMBOLS || mElementState == ELEMENT_SYMBOLS_SHIFT;
}
public boolean isPhoneKeyboard() {
- return mMode == MODE_PHONE;
+ return mElementState == ELEMENT_PHONE || mElementState == ELEMENT_PHONE_SHIFT;
}
public boolean isPhoneShiftKeyboard() {
- return mXmlId == R.xml.kbd_phone_shift;
+ return mElementState == ELEMENT_PHONE_SHIFT;
+ }
+
+ public boolean navigateAction() {
+ // Note: Turn off checking navigation flag to show TAB key for now.
+ boolean navigateAction = InputTypeCompatUtils.isWebInputType(mInputType);
+// || EditorInfoCompatUtils.hasFlagNavigateNext(mImeOptions)
+// || EditorInfoCompatUtils.hasFlagNavigatePrevious(mImeOptions);
+ return navigateAction;
+ }
+
+ public boolean passwordInput() {
+ return InputTypeCompatUtils.isPasswordInputType(mInputType)
+ || InputTypeCompatUtils.isVisiblePasswordInputType(mInputType);
+ }
+
+ public int imeAction() {
+ // We are interested only in {@link EditorInfo#IME_MASK_ACTION} enum value and
+ // {@link EditorInfo#IME_FLAG_NO_ENTER_ACTION}.
+ return mImeOptions & (
+ EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION);
+ }
+
+ public boolean hasSettingsKey() {
+ return mSettingsKeyEnabled && !mClobberSettingsKey;
+ }
+
+ public int f2KeyMode() {
+ if (mClobberSettingsKey) {
+ // Never shows the Settings key
+ return KeyboardId.F2KEY_MODE_SHORTCUT_IME;
+ }
+
+ if (mSettingsKeyEnabled) {
+ return KeyboardId.F2KEY_MODE_SETTINGS;
+ } else {
+ // It should be alright to fall back to the Settings key on 7-inch layouts
+ // even when the Settings key is not explicitly enabled.
+ return KeyboardId.F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS;
+ }
}
@Override
@@ -139,22 +206,6 @@ public class KeyboardId {
return other instanceof KeyboardId && equals((KeyboardId) other);
}
- private boolean equals(KeyboardId other) {
- return other.mLocale.equals(this.mLocale)
- && other.mOrientation == this.mOrientation
- && other.mWidth == this.mWidth
- && other.mMode == this.mMode
- && other.mXmlId == this.mXmlId
- && other.mNavigateAction == this.mNavigateAction
- && other.mPasswordInput == this.mPasswordInput
- && other.mHasSettingsKey == this.mHasSettingsKey
- && other.mF2KeyMode == this.mF2KeyMode
- && other.mClobberSettingsKey == this.mClobberSettingsKey
- && other.mShortcutKeyEnabled == this.mShortcutKeyEnabled
- && other.mHasShortcutKey == this.mHasShortcutKey
- && other.mImeAction == this.mImeAction;
- }
-
@Override
public int hashCode() {
return mHashCode;
@@ -162,17 +213,17 @@ public class KeyboardId {
@Override
public String toString() {
- return String.format("[%s.xml %s %s%d %s %s %s%s%s%s%s%s%s]",
- mXmlName,
+ return String.format("[%s %s %s%d %s %s %s%s%s%s%s%s%s]",
+ elementStateToString(mElementState),
mLocale,
(mOrientation == 1 ? "port" : "land"), mWidth,
modeName(mMode),
- EditorInfoCompatUtils.imeOptionsName(mImeAction),
- f2KeyModeName(mF2KeyMode),
+ EditorInfoCompatUtils.imeOptionsName(imeAction()),
+ f2KeyModeName(f2KeyMode()),
(mClobberSettingsKey ? " clobberSettingsKey" : ""),
- (mNavigateAction ? " navigateAction" : ""),
- (mPasswordInput ? " passwordInput" : ""),
- (mHasSettingsKey ? " hasSettingsKey" : ""),
+ (navigateAction() ? " navigateAction" : ""),
+ (passwordInput() ? " passwordInput" : ""),
+ (hasSettingsKey() ? " hasSettingsKey" : ""),
(mShortcutKeyEnabled ? " shortcutKeyEnabled" : ""),
(mHasShortcutKey ? " hasShortcutKey" : "")
);
@@ -186,6 +237,24 @@ public class KeyboardId {
&& TextUtils.equals(a.privateImeOptions, b.privateImeOptions);
}
+ public static String elementStateToString(int elementState) {
+ switch (elementState) {
+ case ELEMENT_ALPHABET: return "alphabet";
+ /* TODO: Implement alphabet variant shift keyboard.
+ case ELEMENT_ALPHABET_MANUAL_TEMPORARY_SHIFT: return "alphabetManualTemporaryShift";
+ case ELEMENT_ALPHABET_AUTOMATIC_TEMPORARY_SHIFT: return "alphabetAutomaticTemporaryShift";
+ case ELEMENT_ALPHABET_SHIFT_LOCK: return "alphabetShiftLock";
+ case ELEMENT_ALPHABET_SHIFT_LOCK_SHIFT: return "alphabetShiftLockShift";
+ */
+ case ELEMENT_SYMBOLS: return "symbols";
+ case ELEMENT_SYMBOLS_SHIFT: return "symbolsShift";
+ case ELEMENT_PHONE: return "phone";
+ case ELEMENT_PHONE_SHIFT: return "phoneShift";
+ case ELEMENT_NUMBER: return "number";
+ default: return null;
+ }
+ }
+
public static String modeName(int mode) {
switch (mode) {
case MODE_TEXT: return "text";
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
index a803188da..a28cfa85d 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
@@ -19,15 +19,25 @@ package com.android.inputmethod.keyboard;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
import android.util.DisplayMetrics;
+import android.util.Xml;
import android.view.inputmethod.EditorInfo;
+import com.android.inputmethod.keyboard.internal.XmlParseUtils;
import com.android.inputmethod.latin.LatinIME;
+import com.android.inputmethod.latin.LocaleUtils;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SettingsValues;
import com.android.inputmethod.latin.SubtypeSwitcher;
import com.android.inputmethod.latin.Utils;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.HashMap;
import java.util.Locale;
/**
@@ -37,6 +47,9 @@ import java.util.Locale;
* A {@link KeyboardSet} needs to be created for each {@link android.view.inputmethod.EditorInfo}.
*/
public class KeyboardSet {
+ private static final String TAG_KEYBOARD_SET = "KeyboardSet";
+ private static final String TAG_ELEMENT = "Element";
+
// TODO: Make these KeyboardId private.
public final KeyboardId mAlphabetId;
public final KeyboardId mSymbolsId;
@@ -52,12 +65,14 @@ public class KeyboardSet {
private final Resources mResources;
private final EditorInfo mEditorInfo;
+ private final HashMap<Integer, Integer> mElementKeyboards =
+ new HashMap<Integer, Integer>();
+
private final int mMode;
+ private final boolean mSettingsKeyEnabled;
private final boolean mVoiceKeyEnabled;
- private final boolean mNoSettingsKey;
- private final boolean mHasSettingsKey;
- private final int mF2KeyMode;
private final boolean mVoiceKeyOnMain;
+ private final boolean mNoSettingsKey;
private final Locale mLocale;
private final Configuration mConf;
private final DisplayMetrics mMetrics;
@@ -69,7 +84,7 @@ public class KeyboardSet {
final String packageName = context.getPackageName();
mMode = Utils.getKeyboardMode(mEditorInfo);
- final boolean settingsKeyEnabled = settingsValues.isSettingsKeyEnabled();
+ mSettingsKeyEnabled = settingsValues.isSettingsKeyEnabled();
@SuppressWarnings("deprecation")
final boolean noMicrophone = Utils.inPrivateImeOptions(
packageName, LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo)
@@ -79,8 +94,6 @@ public class KeyboardSet {
mVoiceKeyOnMain = settingsValues.isVoiceKeyOnMain();
mNoSettingsKey = Utils.inPrivateImeOptions(
packageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, editorInfo);
- mHasSettingsKey = settingsKeyEnabled && !mNoSettingsKey;
- mF2KeyMode = getF2KeyMode(settingsKeyEnabled, mNoSettingsKey);
final boolean forceAscii = Utils.inPrivateImeOptions(
packageName, LatinIME.IME_OPTION_FORCE_ASCII, editorInfo);
final boolean asciiCapable = subtypeSwitcher.currentSubtypeContainsExtraValueKey(
@@ -91,44 +104,127 @@ public class KeyboardSet {
}
public KeyboardSet build() {
+ final Locale savedLocale = LocaleUtils.setSystemLocale(mResources, mLocale);
+ try {
+ parseKeyboardSet(mResources, R.xml.keyboard_set);
+ } catch (Exception e) {
+ //
+ } finally {
+ LocaleUtils.setSystemLocale(mResources, savedLocale);
+ }
return new KeyboardSet(this);
}
KeyboardId getKeyboardId(boolean isSymbols, boolean isShift) {
- final int xmlId = getXmlId(mMode, isSymbols, isShift);
- final boolean hasShortCutKey = mVoiceKeyEnabled && (isSymbols != mVoiceKeyOnMain);
- return new KeyboardId(mResources.getResourceEntryName(xmlId), xmlId, mLocale,
- mConf.orientation, mMetrics.widthPixels, mMode, mEditorInfo, mHasSettingsKey,
- mF2KeyMode, mNoSettingsKey, mVoiceKeyEnabled, hasShortCutKey);
+ final int elementState = getElementState(mMode, isSymbols, isShift);
+ final int xmlId = mElementKeyboards.get(elementState);
+ final boolean hasShortcutKey = mVoiceKeyEnabled && (isSymbols != mVoiceKeyOnMain);
+ return new KeyboardId(xmlId, elementState, mLocale, mConf.orientation,
+ mMetrics.widthPixels, mMode, mEditorInfo, mSettingsKeyEnabled, mNoSettingsKey,
+ mVoiceKeyEnabled, hasShortcutKey);
}
- private static int getXmlId(int mode, boolean isSymbols, boolean isShift) {
+ private static int getElementState(int mode, boolean isSymbols, boolean isShift) {
switch (mode) {
case KeyboardId.MODE_PHONE:
- return (isSymbols && isShift) ? R.xml.kbd_phone_shift : R.xml.kbd_phone;
+ return (isSymbols && isShift)
+ ? KeyboardId.ELEMENT_PHONE_SHIFT : KeyboardId.ELEMENT_PHONE;
case KeyboardId.MODE_NUMBER:
- return R.xml.kbd_number;
+ return KeyboardId.ELEMENT_NUMBER;
default:
if (isSymbols) {
- return isShift ? R.xml.kbd_symbols_shift : R.xml.kbd_symbols;
+ return isShift ? KeyboardId.ELEMENT_SYMBOLS_SHIFT : KeyboardId.ELEMENT_SYMBOLS;
+ }
+ return KeyboardId.ELEMENT_ALPHABET;
+ }
+ }
+
+ private void parseKeyboardSet(Resources res, int resId) throws XmlPullParserException,
+ IOException {
+ final XmlResourceParser parser = res.getXml(resId);
+ try {
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_KEYBOARD_SET.equals(tag)) {
+ parseKeyboardSetContent(parser);
+ } else {
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD_SET);
+ }
+ }
}
- return R.xml.kbd_qwerty;
+ } finally {
+ parser.close();
}
}
- private static int getF2KeyMode(boolean settingsKeyEnabled, boolean noSettingsKey) {
- if (noSettingsKey) {
- // Never shows the Settings key
- return KeyboardId.F2KEY_MODE_SHORTCUT_IME;
+ private void parseKeyboardSetContent(XmlPullParser parser) throws XmlPullParserException,
+ IOException {
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_ELEMENT.equals(tag)) {
+ parseKeyboardSetElement(parser);
+ } else {
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD_SET);
+ }
+ } else if (event == XmlPullParser.END_TAG) {
+ final String tag = parser.getName();
+ if (TAG_KEYBOARD_SET.equals(tag)) {
+ break;
+ } else {
+ throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEYBOARD_SET);
+ }
+ }
}
+ }
- if (settingsKeyEnabled) {
- return KeyboardId.F2KEY_MODE_SETTINGS;
- } else {
- // It should be alright to fall back to the Settings key on 7-inch layouts
- // even when the Settings key is not explicitly enabled.
- return KeyboardId.F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS;
+ private void parseKeyboardSetElement(XmlPullParser parser) throws XmlPullParserException,
+ IOException {
+ final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.KeyboardSet_Element);
+ try {
+ XmlParseUtils.checkAttributeExists(a,
+ R.styleable.KeyboardSet_Element_elementName, "elementName",
+ TAG_ELEMENT, parser);
+ XmlParseUtils.checkAttributeExists(a,
+ R.styleable.KeyboardSet_Element_elementKeyboard, "elementKeyboard",
+ TAG_ELEMENT, parser);
+ XmlParseUtils.checkEndTag(TAG_ELEMENT, parser);
+
+ final int elementName = a.getInt(
+ R.styleable.KeyboardSet_Element_elementName, 0);
+ final int elementKeyboard = a.getResourceId(
+ R.styleable.KeyboardSet_Element_elementKeyboard, 0);
+ mElementKeyboards.put(elementName, elementKeyboard);
+ } finally {
+ a.recycle();
+ }
+ }
+ }
+
+ public static String parseKeyboardLocale(Resources res, int resId)
+ throws XmlPullParserException, IOException {
+ final XmlPullParser parser = res.getXml(resId);
+ if (parser == null) return "";
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_KEYBOARD_SET.equals(tag)) {
+ final TypedArray keyboardSetAttr = res.obtainAttributes(
+ Xml.asAttributeSet(parser), R.styleable.KeyboardSet);
+ final String locale = keyboardSetAttr.getString(
+ R.styleable.KeyboardSet_keyboardLocale);
+ keyboardSetAttr.recycle();
+ return locale;
+ } else {
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD_SET);
+ }
}
}
+ return "";
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 165e9aec7..1f3006d9f 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -191,11 +191,11 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
if (DEBUG_CACHE) {
Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": "
+ ((ref == null) ? "LOAD" : "GCed") + " id=" + id
- + " theme=" + Keyboard.themeName(keyboard.mThemeId));
+ + " theme=" + themeName(keyboard.mThemeId));
}
} else if (DEBUG_CACHE) {
Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT id=" + id
- + " theme=" + Keyboard.themeName(keyboard.mThemeId));
+ + " theme=" + themeName(keyboard.mThemeId));
}
keyboard.onAutoCorrectionStateChanged(mIsAutoCorrectionActive);
@@ -463,4 +463,17 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
}
}
}
+
+ private static String themeName(int themeId) {
+ // This should be aligned with theme-*.xml resource files' themeId attribute.
+ switch (themeId) {
+ case 0: return "Basic";
+ case 1: return "BasicHighContrast";
+ case 5: return "IceCreamSandwich";
+ case 6: return "Stone";
+ case 7: return "StoneBold";
+ case 8: return "GingerBread";
+ default: return null;
+ }
+ }
}
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index af5f808fd..e56f2ea84 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -409,19 +409,16 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
invokeReleaseKey(primaryCode);
return true;
}
- }
- if (primaryCode == Keyboard.CODE_SETTINGS || primaryCode == Keyboard.CODE_SPACE) {
- // Both long pressing settings key and space key invoke IME switcher dialog.
- if (invokeCustomRequest(LatinIME.CODE_SHOW_INPUT_METHOD_PICKER)) {
- tracker.onLongPressed();
- invokeReleaseKey(primaryCode);
- return true;
- } else {
- return openMoreKeysPanel(parentKey, tracker);
+ if (primaryCode == Keyboard.CODE_SPACE) {
+ // Long pressing the space key invokes IME switcher dialog.
+ if (invokeCustomRequest(LatinIME.CODE_SHOW_INPUT_METHOD_PICKER)) {
+ tracker.onLongPressed();
+ invokeReleaseKey(primaryCode);
+ return true;
+ }
}
- } else {
- return openMoreKeysPanel(parentKey, tracker);
}
+ return openMoreKeysPanel(parentKey, tracker);
}
private boolean invokeCustomRequest(int code) {
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
index ac9290bfd..e0f21a247 100644
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
@@ -207,7 +207,7 @@ public class MiniKeyboard extends Keyboard {
public Builder(KeyboardView view, int xmlId, Key parentKey, Keyboard parentKeyboard) {
super(view.getContext(), new MiniKeyboardParams());
- load(parentKeyboard.mId.cloneWithNewXml(mResources.getResourceEntryName(xmlId), xmlId));
+ load(parentKeyboard.mId.cloneWithNewXml(xmlId));
// TODO: Mini keyboard's vertical gap is currently calculated heuristically.
// Should revise the algorithm.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
index 218793500..3324fa6af 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
@@ -19,10 +19,10 @@ package com.android.inputmethod.keyboard.internal;
import android.content.res.TypedArray;
import android.util.Log;
-import com.android.inputmethod.keyboard.internal.KeyboardBuilder.ParseException;
import com.android.inputmethod.latin.R;
import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
import java.util.ArrayList;
import java.util.HashMap;
@@ -43,7 +43,7 @@ public class KeyStyles {
}
/* package */ static class EmptyKeyStyle implements KeyStyle {
- private EmptyKeyStyle() {
+ EmptyKeyStyle() {
// Nothing to do.
}
@@ -118,7 +118,7 @@ public class KeyStyles {
}
}
- private static class DeclaredKeyStyle extends EmptyKeyStyle {
+ /* package */ static class DeclaredKeyStyle extends EmptyKeyStyle {
private final HashMap<Integer, Object> mAttributes = new HashMap<Integer, Object>();
@Override
@@ -145,11 +145,11 @@ public class KeyStyles {
return super.getFlag(a, index, defaultValue) | (value != null ? value : 0);
}
- private DeclaredKeyStyle() {
+ DeclaredKeyStyle() {
super();
}
- private void parseKeyStyleAttributes(TypedArray keyAttr) {
+ void parseKeyStyleAttributes(TypedArray keyAttr) {
// TODO: Currently not all Key attributes can be declared as style.
readInt(keyAttr, R.styleable.Keyboard_Key_code);
readInt(keyAttr, R.styleable.Keyboard_Key_altCode);
@@ -188,18 +188,19 @@ public class KeyStyles {
mAttributes.put(index, value);
}
- private void addParent(DeclaredKeyStyle parentStyle) {
+ void addParent(DeclaredKeyStyle parentStyle) {
mAttributes.putAll(parentStyle.mAttributes);
}
}
public void parseKeyStyleAttributes(TypedArray keyStyleAttr, TypedArray keyAttrs,
- XmlPullParser parser) {
+ XmlPullParser parser) throws XmlPullParserException {
final String styleName = keyStyleAttr.getString(R.styleable.Keyboard_KeyStyle_styleName);
if (DEBUG) Log.d(TAG, String.format("<%s styleName=%s />",
KeyboardBuilder.TAG_KEY_STYLE, styleName));
if (mStyles.containsKey(styleName))
- throw new ParseException("duplicate key style declared: " + styleName, parser);
+ throw new XmlParseUtils.ParseException(
+ "duplicate key style declared: " + styleName, parser);
final DeclaredKeyStyle style = new DeclaredKeyStyle();
if (keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_parentStyle)) {
@@ -207,7 +208,8 @@ public class KeyStyles {
R.styleable.Keyboard_KeyStyle_parentStyle);
final DeclaredKeyStyle parent = mStyles.get(parentStyle);
if (parent == null)
- throw new ParseException("Unknown parentStyle " + parentStyle, parser);
+ throw new XmlParseUtils.ParseException(
+ "Unknown parentStyle " + parentStyle, parser);
style.addParent(parent);
}
style.parseKeyStyleAttributes(keyAttrs);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
index de64639b0..7382cfa7f 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
@@ -292,7 +292,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
return new Keyboard(mParams);
}
- private void parseKeyboard(XmlResourceParser parser)
+ private void parseKeyboard(XmlPullParser parser)
throws XmlPullParserException, IOException {
if (DEBUG) Log.d(TAG, String.format("<%s> %s", TAG_KEYBOARD, mParams.mId));
int event;
@@ -305,36 +305,12 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
parseKeyboardContent(parser, false);
break;
} else {
- throw new IllegalStartTag(parser, TAG_KEYBOARD);
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD);
}
}
}
}
- public static String parseKeyboardLocale(
- Context context, int resId) throws XmlPullParserException, IOException {
- final Resources res = context.getResources();
- final XmlPullParser parser = res.getXml(resId);
- if (parser == null) return "";
- int event;
- while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
- if (event == XmlPullParser.START_TAG) {
- final String tag = parser.getName();
- if (TAG_KEYBOARD.equals(tag)) {
- final TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard);
- final String locale = keyboardAttr.getString(
- R.styleable.Keyboard_keyboardLocale);
- keyboardAttr.recycle();
- return locale;
- } else {
- throw new IllegalStartTag(parser, TAG_KEYBOARD);
- }
- }
- }
- return "";
- }
-
private void parseKeyboardAttributes(XmlPullParser parser) {
final int displayWidth = mDisplayMetrics.widthPixels;
final TypedArray keyboardAttr = mContext.obtainStyledAttributes(
@@ -417,7 +393,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
} else if (TAG_KEY_STYLE.equals(tag)) {
parseKeyStyle(parser, skip);
} else {
- throw new IllegalStartTag(parser, TAG_ROW);
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_ROW);
}
} else if (event == XmlPullParser.END_TAG) {
final String tag = parser.getName();
@@ -431,20 +407,20 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
} else if (TAG_KEY_STYLE.equals(tag)) {
continue;
} else {
- throw new IllegalEndTag(parser, TAG_ROW);
+ throw new XmlParseUtils.IllegalEndTag(parser, TAG_ROW);
}
}
}
}
- private Row parseRowAttributes(XmlPullParser parser) {
+ private Row parseRowAttributes(XmlPullParser parser) throws XmlPullParserException {
final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
R.styleable.Keyboard);
try {
if (a.hasValue(R.styleable.Keyboard_horizontalGap))
- throw new IllegalAttribute(parser, "horizontalGap");
+ throw new XmlParseUtils.IllegalAttribute(parser, "horizontalGap");
if (a.hasValue(R.styleable.Keyboard_verticalGap))
- throw new IllegalAttribute(parser, "verticalGap");
+ throw new XmlParseUtils.IllegalAttribute(parser, "verticalGap");
return new Row(mResources, mParams, parser, mCurrentY);
} finally {
a.recycle();
@@ -468,7 +444,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
} else if (TAG_KEY_STYLE.equals(tag)) {
parseKeyStyle(parser, skip);
} else {
- throw new IllegalStartTag(parser, TAG_KEY);
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEY);
}
} else if (event == XmlPullParser.END_TAG) {
final String tag = parser.getName();
@@ -484,7 +460,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
} else if (TAG_KEY_STYLE.equals(tag)) {
continue;
} else {
- throw new IllegalEndTag(parser, TAG_KEY);
+ throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEY);
}
}
}
@@ -493,13 +469,13 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
private void parseKey(XmlPullParser parser, Row row, boolean skip)
throws XmlPullParserException, IOException {
if (skip) {
- checkEndTag(TAG_KEY, parser);
+ XmlParseUtils.checkEndTag(TAG_KEY, parser);
} else {
final Key key = new Key(mResources, mParams, row, parser, mKeyStyles);
if (DEBUG) Log.d(TAG, String.format("<%s%s keyLabel=%s code=%d moreKeys=%s />",
TAG_KEY, (key.isEnabled() ? "" : " disabled"), key.mLabel, key.mCode,
Arrays.toString(key.mMoreKeys)));
- checkEndTag(TAG_KEY, parser);
+ XmlParseUtils.checkEndTag(TAG_KEY, parser);
endKey(key);
}
}
@@ -507,11 +483,11 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
private void parseSpacer(XmlPullParser parser, Row row, boolean skip)
throws XmlPullParserException, IOException {
if (skip) {
- checkEndTag(TAG_SPACER, parser);
+ XmlParseUtils.checkEndTag(TAG_SPACER, parser);
} else {
final Key.Spacer spacer = new Key.Spacer(mResources, mParams, row, parser, mKeyStyles);
if (DEBUG) Log.d(TAG, String.format("<%s />", TAG_SPACER));
- checkEndTag(TAG_SPACER, parser);
+ XmlParseUtils.checkEndTag(TAG_SPACER, parser);
endKey(spacer);
}
}
@@ -529,17 +505,21 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
private void parseIncludeInternal(XmlPullParser parser, Row row, boolean skip)
throws XmlPullParserException, IOException {
if (skip) {
- checkEndTag(TAG_INCLUDE, parser);
+ XmlParseUtils.checkEndTag(TAG_INCLUDE, parser);
} else {
final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
R.styleable.Keyboard_Include);
- final int keyboardLayout = a.getResourceId(
- R.styleable.Keyboard_Include_keyboardLayout, 0);
- a.recycle();
+ int keyboardLayout = 0;
+ try {
+ XmlParseUtils.checkAttributeExists(a,
+ R.styleable.Keyboard_Include_keyboardLayout, "keyboardLayout",
+ TAG_INCLUDE, parser);
+ keyboardLayout = a.getResourceId(R.styleable.Keyboard_Include_keyboardLayout, 0);
+ } finally {
+ a.recycle();
+ }
- checkEndTag(TAG_INCLUDE, parser);
- if (keyboardLayout == 0)
- throw new ParseException("No keyboardLayout attribute in <include/>", parser);
+ XmlParseUtils.checkEndTag(TAG_INCLUDE, parser);
if (DEBUG) Log.d(TAG, String.format("<%s keyboardLayout=%s />",
TAG_INCLUDE, mResources.getResourceEntryName(keyboardLayout)));
final XmlResourceParser parserForInclude = mResources.getXml(keyboardLayout);
@@ -565,7 +545,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
}
break;
} else {
- throw new ParseException(
+ throw new XmlParseUtils.ParseException(
"Included keyboard layout must have <merge> root element", parser);
}
}
@@ -595,7 +575,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
} else if (TAG_DEFAULT.equals(tag)) {
selected |= parseDefault(parser, row, selected ? true : skip);
} else {
- throw new IllegalStartTag(parser, TAG_KEY);
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEY);
}
} else if (event == XmlPullParser.END_TAG) {
final String tag = parser.getName();
@@ -603,7 +583,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
if (DEBUG) Log.d(TAG, String.format("</%s>", TAG_SWITCH));
break;
} else {
- throw new IllegalEndTag(parser, TAG_KEY);
+ throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEY);
}
}
}
@@ -633,13 +613,13 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
final boolean modeMatched = matchTypedValue(a,
R.styleable.Keyboard_Case_mode, id.mMode, KeyboardId.modeName(id.mMode));
final boolean navigateActionMatched = matchBoolean(a,
- R.styleable.Keyboard_Case_navigateAction, id.mNavigateAction);
+ R.styleable.Keyboard_Case_navigateAction, id.navigateAction());
final boolean passwordInputMatched = matchBoolean(a,
- R.styleable.Keyboard_Case_passwordInput, id.mPasswordInput);
+ R.styleable.Keyboard_Case_passwordInput, id.passwordInput());
final boolean hasSettingsKeyMatched = matchBoolean(a,
- R.styleable.Keyboard_Case_hasSettingsKey, id.mHasSettingsKey);
+ R.styleable.Keyboard_Case_hasSettingsKey, id.hasSettingsKey());
final boolean f2KeyModeMatched = matchInteger(a,
- R.styleable.Keyboard_Case_f2KeyMode, id.mF2KeyMode);
+ R.styleable.Keyboard_Case_f2KeyMode, id.f2KeyMode());
final boolean clobberSettingsKeyMatched = matchBoolean(a,
R.styleable.Keyboard_Case_clobberSettingsKey, id.mClobberSettingsKey);
final boolean shortcutKeyEnabledMatched = matchBoolean(a,
@@ -651,7 +631,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
// {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_ENTER_ACTION}. So matching
// this attribute with id.mImeOptions as integer value is enough for our purpose.
final boolean imeActionMatched = matchInteger(a,
- R.styleable.Keyboard_Case_imeAction, id.mImeAction);
+ R.styleable.Keyboard_Case_imeAction, id.imeAction());
final boolean localeCodeMatched = matchString(a,
R.styleable.Keyboard_Case_localeCode, id.mLocale.toString());
final boolean languageCodeMatched = matchString(a,
@@ -740,14 +720,15 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
return true;
}
- private void parseKeyStyle(XmlPullParser parser, boolean skip) {
+ private void parseKeyStyle(XmlPullParser parser, boolean skip)
+ throws XmlPullParserException {
TypedArray keyStyleAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
R.styleable.Keyboard_KeyStyle);
TypedArray keyAttrs = mResources.obtainAttributes(Xml.asAttributeSet(parser),
R.styleable.Keyboard_Key);
try {
if (!keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_styleName))
- throw new ParseException("<" + TAG_KEY_STYLE
+ throw new XmlParseUtils.ParseException("<" + TAG_KEY_STYLE
+ "/> needs styleName attribute", parser);
if (!skip)
mKeyStyles.parseKeyStyleAttributes(keyStyleAttr, keyAttrs, parser);
@@ -757,13 +738,6 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
}
}
- private static void checkEndTag(String tag, XmlPullParser parser)
- throws XmlPullParserException, IOException {
- if (parser.next() == XmlPullParser.END_TAG && tag.equals(parser.getName()))
- return;
- throw new NonEmptyTag(tag, parser);
- }
-
private void startKeyboard() {
mCurrentY += mParams.mTopPadding;
mTopEdge = true;
@@ -802,6 +776,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
}
private void endKeyboard() {
+ // nothing to do here.
}
private void addEdgeSpace(float width, Row row) {
@@ -848,41 +823,6 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
return v.type == TypedValue.TYPE_STRING;
}
- @SuppressWarnings("serial")
- public static class ParseException extends InflateException {
- public ParseException(String msg, XmlPullParser parser) {
- super(msg + " at line " + parser.getLineNumber());
- }
- }
-
- @SuppressWarnings("serial")
- private static class IllegalStartTag extends ParseException {
- public IllegalStartTag(XmlPullParser parser, String parent) {
- super("Illegal start tag " + parser.getName() + " in " + parent, parser);
- }
- }
-
- @SuppressWarnings("serial")
- private static class IllegalEndTag extends ParseException {
- public IllegalEndTag(XmlPullParser parser, String parent) {
- super("Illegal end tag " + parser.getName() + " in " + parent, parser);
- }
- }
-
- @SuppressWarnings("serial")
- private static class IllegalAttribute extends ParseException {
- public IllegalAttribute(XmlPullParser parser, String attribute) {
- super("Tag " + parser.getName() + " has illegal attribute " + attribute, parser);
- }
- }
-
- @SuppressWarnings("serial")
- private static class NonEmptyTag extends ParseException {
- public NonEmptyTag(String tag, XmlPullParser parser) {
- super(tag + " must be empty tag", parser);
- }
- }
-
private static String textAttr(String value, String name) {
return value != null ? String.format(" %s=%s", name, value) : "";
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/XmlParseUtils.java b/java/src/com/android/inputmethod/keyboard/internal/XmlParseUtils.java
new file mode 100644
index 000000000..170be347b
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/XmlParseUtils.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+package com.android.inputmethod.keyboard.internal;
+
+import android.content.res.TypedArray;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+public class XmlParseUtils {
+ @SuppressWarnings("serial")
+ public static class ParseException extends XmlPullParserException {
+ public ParseException(String msg, XmlPullParser parser) {
+ super(msg + " at line " + parser.getLineNumber()
+ + ", column " + parser.getColumnNumber());
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static class IllegalStartTag extends ParseException {
+ public IllegalStartTag(XmlPullParser parser, String parent) {
+ super("Illegal start tag " + parser.getName() + " in " + parent, parser);
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static class IllegalEndTag extends ParseException {
+ public IllegalEndTag(XmlPullParser parser, String parent) {
+ super("Illegal end tag " + parser.getName() + " in " + parent, parser);
+ }
+ }
+
+ @SuppressWarnings("serial")
+ static class IllegalAttribute extends ParseException {
+ public IllegalAttribute(XmlPullParser parser, String attribute) {
+ super("Tag " + parser.getName() + " has illegal attribute " + attribute, parser);
+ }
+ }
+
+ @SuppressWarnings("serial")
+ static class NonEmptyTag extends ParseException{
+ public NonEmptyTag(String tag, XmlPullParser parser) {
+ super(tag + " must be empty tag", parser);
+ }
+ }
+
+ public static void checkEndTag(String tag, XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ if (parser.next() == XmlPullParser.END_TAG && tag.equals(parser.getName()))
+ return;
+ throw new NonEmptyTag(tag, parser);
+ }
+
+ public static void checkAttributeExists(TypedArray attr, int attrId, String attrName,
+ String tag, XmlPullParser parser) throws XmlPullParserException {
+ if (attr.hasValue(attrId))
+ return;
+ throw new ParseException(
+ "No " + attrName + " attribute found in <" + tag + "/>", parser);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 2d7eed7ab..98fea1b5b 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -722,6 +722,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
: String.format("inputType=0x%08x imeOptions=0x%08x",
editorInfo.inputType, editorInfo.imeOptions)));
}
+ LatinImeLogger.onStartInputView(editorInfo);
// In landscape mode, this method gets called without the input view being created.
if (inputView == null) {
return;
@@ -1510,13 +1511,16 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (null != ic) removeTrailingSpaceWhileInBatchEdit(ic);
}
+ boolean isComposingWord = mHasUncommittedTypedChars;
int code = primaryCode;
if ((isAlphabet(code) || mSettingsValues.isSymbolExcludedFromWordSeparators(code))
&& isSuggestionsRequested() && !isCursorTouchingWord()) {
- if (!mHasUncommittedTypedChars) {
+ if (!isComposingWord) {
// Reset entirely the composing state anyway, then start composing a new word unless
- // the character is a single quote.
- mHasUncommittedTypedChars = (Keyboard.CODE_SINGLE_QUOTE != code);
+ // the character is a single quote. The idea here is, single quote is not a
+ // separator and it should be treated as a normal character, except in the first
+ // position where it should not start composing a word.
+ isComposingWord = (Keyboard.CODE_SINGLE_QUOTE != code);
mWordComposer.reset();
clearSuggestions();
mComposingStateManager.onFinishComposingText();
@@ -1543,7 +1547,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
}
}
- if (mHasUncommittedTypedChars) {
+ if (isComposingWord) {
+ mHasUncommittedTypedChars = true;
mWordComposer.add(code, keyCodes, x, y);
if (ic != null) {
// If it's the first letter, make note of auto-caps state
@@ -1581,7 +1586,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mHandler.postUpdateSuggestions();
}
- boolean pickedDefault = false;
// Handle separator
final InputConnection ic = getCurrentInputConnection();
if (ic != null) {
@@ -1598,7 +1602,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled
&& !mInputTypeNoAutoCorrect;
if (shouldAutoCorrect && primaryCode != Keyboard.CODE_SINGLE_QUOTE) {
- pickedDefault = pickDefaultSuggestion(primaryCode);
+ commitCurrentAutoCorrection(primaryCode, ic);
} else {
commitTyped(ic);
}
@@ -1651,21 +1655,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
Utils.Stats.onSeparator((char)primaryCode, x, y);
- if (pickedDefault) {
- final CharSequence autoCorrection = mWordComposer.getAutoCorrectionOrNull();
- final String typedWord = mWordComposer.getTypedWord();
- if (TextUtils.isEmpty(typedWord)) {
- throw new RuntimeException("We have non-committed chars but the typed word "
- + "is empty? Impossible! I must commit suicide.");
- }
- if (!typedWord.equals(autoCorrection)) {
- // TODO: if the commitCorrection method is not supported by the platform
- // this will do nothing and the correction will not be committed at all. What
- // happens on Froyo/Gingerbread, where this API is not present?
- InputConnectionCompatUtils.commitCorrection(
- ic, mLastSelectionEnd - typedWord.length(), typedWord, autoCorrection);
- }
- }
mKeyboardSwitcher.updateShiftState();
if (ic != null) {
ic.endBatchEdit();
@@ -1785,7 +1774,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
return;
}
- final WordComposer wordComposer = mWordComposer;
// TODO: May need a better way of retrieving previous word
final InputConnection ic = getCurrentInputConnection();
final CharSequence prevWord;
@@ -1795,18 +1783,18 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
prevWord = EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators);
}
// getSuggestedWordBuilder handles gracefully a null value of prevWord
- final SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(wordComposer,
+ final SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(mWordComposer,
prevWord, mKeyboardSwitcher.getLatinKeyboard().getProximityInfo(), mCorrectionMode);
boolean autoCorrectionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasAutoCorrection();
- final CharSequence typedWord = wordComposer.getTypedWord();
+ final CharSequence typedWord = mWordComposer.getTypedWord();
// Here, we want to promote a whitelisted word if exists.
// TODO: Change this scheme - a boolean is not enough. A whitelisted word may be "valid"
// but still autocorrected from - in the case the whitelist only capitalizes the word.
// The whitelist should be case-insensitive, so it's not possible to be consistent with
// a boolean flag. Right now this is handled with a slight hack in
// WhitelistDictionary#shouldForciblyAutoCorrectFrom.
- final int quotesCount = wordComposer.trailingSingleQuotesCount();
+ final int quotesCount = mWordComposer.trailingSingleQuotesCount();
final boolean allowsToBeAutoCorrected = AutoCorrection.allowsToBeAutoCorrected(
mSuggest.getUnigramDictionaries(),
// If the typed string ends with a single quote, for dictionary lookup purposes
@@ -1822,7 +1810,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
autoCorrectionAvailable |= (!allowsToBeAutoCorrected);
}
// Don't auto-correct words with multiple capital letter
- autoCorrectionAvailable &= !wordComposer.isMostlyCaps();
+ autoCorrectionAvailable &= !mWordComposer.isMostlyCaps();
// Basically, we update the suggestion strip only when suggestion count > 1. However,
// there is an exception: We update the suggestion strip whenever typed word's length
@@ -1871,7 +1859,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
setSuggestionStripShown(isSuggestionsStripVisible());
}
- private boolean pickDefaultSuggestion(int separatorCode) {
+ private void commitCurrentAutoCorrection(final int separatorCodePoint,
+ final InputConnection ic) {
// Complete any pending suggestions query first
if (mHandler.hasPendingUpdateSuggestions()) {
mHandler.cancelUpdateSuggestions();
@@ -1880,7 +1869,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
final CharSequence autoCorrection = mWordComposer.getAutoCorrectionOrNull();
if (autoCorrection != null) {
final String typedWord = mWordComposer.getTypedWord();
- Utils.Stats.onAutoCorrection(typedWord, autoCorrection.toString(), separatorCode);
+ if (TextUtils.isEmpty(typedWord)) {
+ throw new RuntimeException("We have an auto-correction but the typed word "
+ + "is empty? Impossible! I must commit suicide.");
+ }
+ Utils.Stats.onAutoCorrection(typedWord, autoCorrection.toString(), separatorCodePoint);
mExpectingUpdateSelection = true;
commitBestWord(autoCorrection);
if (!autoCorrection.equals(typedWord)) {
@@ -1889,9 +1882,13 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Add the word to the user unigram dictionary if it's not a known word
addToUserUnigramAndBigramDictionaries(autoCorrection,
UserUnigramDictionary.FREQUENCY_FOR_TYPED);
- return true;
+ if (!typedWord.equals(autoCorrection) && null != ic) {
+ // This will make the correction flash for a short while as a visual clue
+ // to the user that auto-correction happened.
+ InputConnectionCompatUtils.commitCorrection(ic,
+ mLastSelectionEnd - typedWord.length(), typedWord, autoCorrection);
+ }
}
- return false;
}
@Override
@@ -1959,6 +1956,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} else {
addToOnlyBigramDictionary(suggestion, 1);
}
+ // TODO: the following is fishy, because if !mHasUncommittedTypedChars we are
+ // going to log an empty string
LatinImeLogger.logOnManualSuggestion(mWordComposer.getTypedWord().toString(),
suggestion.toString(), index, suggestions.mWords);
// Follow it with a space
@@ -2399,8 +2398,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
}
- public WordComposer getCurrentWord() {
- return mWordComposer;
+ public boolean isAutoCapitalized() {
+ return mWordComposer.isAutoCapitalized();
}
boolean isSoundOn() {
diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
index cbac4d31c..da5058dd4 100644
--- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java
+++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
@@ -16,11 +16,12 @@
package com.android.inputmethod.latin;
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.latin.Dictionary.DataType;
-
import android.content.Context;
import android.content.SharedPreferences;
+import android.view.inputmethod.EditorInfo;
+
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.latin.Dictionary.DataType;
import java.util.List;
@@ -44,7 +45,7 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
public static void logOnManualSuggestion(
String before, String after, int position, List<CharSequence> suggestions) {
- }
+ }
public static void logOnAutoCorrection(String before, String after, int separatorCode) {
}
@@ -67,6 +68,9 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
public static void logOnWarning(String warning) {
}
+ public static void onStartInputView(EditorInfo editorInfo) {
+ }
+
public static void onStartSuggestion(CharSequence previousWords) {
}
diff --git a/java/src/com/android/inputmethod/latin/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/MoreSuggestions.java
index 9a59ef2e0..86072b64b 100644
--- a/java/src/com/android/inputmethod/latin/MoreSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/MoreSuggestions.java
@@ -178,7 +178,7 @@ public class MoreSuggestions extends Keyboard {
int minWidth, int maxRow) {
final Keyboard keyboard = KeyboardSwitcher.getInstance().getLatinKeyboard();
final int xmlId = R.xml.kbd_suggestions_pane_template;
- load(keyboard.mId.cloneWithNewXml(mResources.getResourceEntryName(xmlId), xmlId));
+ load(keyboard.mId.cloneWithNewXml(xmlId));
mParams.mVerticalGap = mParams.mTopPadding = keyboard.mVerticalGap / 2;
final int count = mParams.layout(suggestions, fromPos, maxWidth, minWidth, maxRow,
diff --git a/java/src/com/android/inputmethod/latin/UserBigramDictionary.java b/java/src/com/android/inputmethod/latin/UserBigramDictionary.java
index 3a1af9311..f80534cb5 100644
--- a/java/src/com/android/inputmethod/latin/UserBigramDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBigramDictionary.java
@@ -159,7 +159,7 @@ public class UserBigramDictionary extends ExpandableDictionary {
*/
public int addBigrams(String word1, String word2) {
// remove caps if second word is autocapitalized
- if (mIme != null && mIme.getCurrentWord().isAutoCapitalized()) {
+ if (mIme != null && mIme.isAutoCapitalized()) {
word2 = Character.toLowerCase(word2.charAt(0)) + word2.substring(1);
}
// Do not insert a word as a bigram of itself
diff --git a/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java b/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java
index de7cb5716..6af20c754 100644
--- a/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java
@@ -149,7 +149,7 @@ public class UserUnigramDictionary extends ExpandableDictionary {
final int length = word.length();
// Don't add very short or very long words.
if (length < 2 || length > getMaxWordLength()) return;
- if (mIme.getCurrentWord().isAutoCapitalized()) {
+ if (mIme.isAutoCapitalized()) {
// Remove caps before adding
word = Character.toLowerCase(word.charAt(0)) + word.substring(1);
}
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index fcaf81cd5..8bbcff758 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -301,7 +301,7 @@ public class WordComposer {
}
/**
- * @return the auto-correction for this world, or null if none.
+ * @return the auto-correction for this word, or null if none.
*/
public CharSequence getAutoCorrectionOrNull() {
return mAutoCorrection;