diff options
Diffstat (limited to 'java')
13 files changed, 317 insertions, 228 deletions
diff --git a/java/res/layout/input_view.xml b/java/res/layout/input_view.xml index 2e0cddc28..b9451f8ae 100644 --- a/java/res/layout/input_view.xml +++ b/java/res/layout/input_view.xml @@ -43,7 +43,7 @@ android:layout_width="@dimen/suggestions_strip_padding" android:layout_height="@dimen/suggestions_strip_height" style="?attr/suggestionsStripBackgroundStyle" /> - <com.android.inputmethod.latin.SuggestionsView + <com.android.inputmethod.latin.suggestions.SuggestionsView android:id="@+id/suggestions_view" android:layout_weight="1.0" android:layout_width="0dp" diff --git a/java/res/layout/more_suggestions.xml b/java/res/layout/more_suggestions.xml index 6aa82e197..1e59b8931 100644 --- a/java/res/layout/more_suggestions.xml +++ b/java/res/layout/more_suggestions.xml @@ -24,7 +24,7 @@ android:orientation="horizontal" style="?attr/miniKeyboardPanelStyle" > - <com.android.inputmethod.latin.MoreSuggestionsView + <com.android.inputmethod.latin.suggestions.MoreSuggestionsView xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" android:id="@+id/more_suggestions_view" android:layout_alignParentBottom="true" diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java index 3b3ff0709..d95c3b3af 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java @@ -60,8 +60,6 @@ public class KeyboardId { public final int mOrientation; public final int mWidth; public final int mMode; - // TODO: Remove this field. - private final int mXmlId; public final int mElementState; private final int mInputType; private final int mImeOptions; @@ -72,23 +70,13 @@ public class KeyboardId { private final int mHashCode; - 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) { + public KeyboardId(int elementState, Locale locale, int orientation, int width, int mode, + int inputType, int imeOptions, boolean settingsKeyEnabled, boolean clobberSettingsKey, + boolean shortcutKeyEnabled, boolean hasShortcutKey) { this.mLocale = locale; this.mOrientation = orientation; this.mWidth = width; this.mMode = mode; - this.mXmlId = xmlId; this.mElementState = elementState; this.mInputType = inputType; this.mImeOptions = imeOptions; @@ -106,7 +94,6 @@ public class KeyboardId { id.mElementState, id.mMode, id.mWidth, - id.mXmlId, id.navigateAction(), id.passwordInput(), id.mSettingsKeyEnabled, @@ -125,7 +112,6 @@ public class KeyboardId { && 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 @@ -136,16 +122,6 @@ public class KeyboardId { && 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 mElementState < ELEMENT_SYMBOLS; } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java index a28cfa85d..e15ce06e3 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java @@ -17,16 +17,16 @@ 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.Log; 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.LatinImeLogger; import com.android.inputmethod.latin.LocaleUtils; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SettingsValues; @@ -37,74 +37,157 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; +import java.lang.ref.SoftReference; import java.util.HashMap; import java.util.Locale; /** - * This class has a set of {@link KeyboardId}s. Each of them represents a different keyboard + * This class represents a set of keyboards. Each of them represents a different keyboard * specific to a keyboard state, such as alphabet, symbols, and so on. Layouts in the same * {@link KeyboardSet} are related to each other. * 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 = KeyboardSet.class.getSimpleName(); + private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG; + + private static final String TAG_KEYBOARD_SET = TAG; private static final String TAG_ELEMENT = "Element"; - // TODO: Make these KeyboardId private. - public final KeyboardId mAlphabetId; - public final KeyboardId mSymbolsId; - public final KeyboardId mSymbolsShiftedId; + private final Context mContext; + private final Params mParams; + + private static class Params { + int mMode; + int mInputType; + int mImeOptions; + boolean mSettingsKeyEnabled; + boolean mVoiceKeyEnabled; + boolean mVoiceKeyOnMain; + boolean mNoSettingsKey; + Locale mLocale; + int mOrientation; + int mWidth; + final HashMap<Integer, Integer> mElementKeyboards = new HashMap<Integer, Integer>(); + Params() {} + } + + private static final HashMap<KeyboardId, SoftReference<LatinKeyboard>> sKeyboardCache = + new HashMap<KeyboardId, SoftReference<LatinKeyboard>>(); + + public static void clearKeyboardCache() { + sKeyboardCache.clear(); + } + + private KeyboardSet(Context context, Params params) { + mContext = context; + mParams = params; + } + + public LatinKeyboard getMainKeyboard() { + return getKeyboard(false, false); + } + + public LatinKeyboard getSymbolsKeyboard() { + return getKeyboard(true, false); + } + + public LatinKeyboard getSymbolsShiftedKeyboard() { + final LatinKeyboard keyboard = getKeyboard(true, true); + // TODO: Remove this logic once we introduce initial keyboard shift state attribute. + // Symbol shift keyboard may have a shift key that has a caps lock style indicator (a.k.a. + // sticky shift key). To show or dismiss the indicator, we need to call setShiftLocked() + // that takes care of the current keyboard having such shift key or not. + keyboard.setShiftLocked(keyboard.hasShiftLockKey()); + return keyboard; + } - KeyboardSet(Builder builder) { - mAlphabetId = builder.getKeyboardId(false, false); - mSymbolsId = builder.getKeyboardId(true, false); - mSymbolsShiftedId = builder.getKeyboardId(true, true); + private LatinKeyboard getKeyboard(boolean isSymbols, boolean isShift) { + final int elementState = Builder.getElementState(mParams.mMode, isSymbols, isShift); + final int xmlId = mParams.mElementKeyboards.get(elementState); + final KeyboardId id = Builder.getKeyboardId(elementState, isSymbols, mParams); + final LatinKeyboard keyboard = getKeyboard(mContext, xmlId, id); + return keyboard; + } + + public KeyboardId getMainKeyboardId() { + final int elementState = Builder.getElementState(mParams.mMode, false, false); + return Builder.getKeyboardId(elementState, false, mParams); + } + + private static LatinKeyboard getKeyboard(Context context, int xmlId, KeyboardId id) { + final Resources res = context.getResources(); + final SubtypeSwitcher subtypeSwitcher = SubtypeSwitcher.getInstance(); + final SoftReference<LatinKeyboard> ref = sKeyboardCache.get(id); + LatinKeyboard keyboard = (ref == null) ? null : ref.get(); + if (keyboard == null) { + final Locale savedLocale = LocaleUtils.setSystemLocale(res, id.mLocale); + try { + final LatinKeyboard.Builder builder = new LatinKeyboard.Builder(context); + builder.load(xmlId, id); + builder.setTouchPositionCorrectionEnabled( + subtypeSwitcher.currentSubtypeContainsExtraValueKey( + LatinIME.SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION)); + keyboard = builder.build(); + } finally { + LocaleUtils.setSystemLocale(res, savedLocale); + } + sKeyboardCache.put(id, new SoftReference<LatinKeyboard>(keyboard)); + + if (DEBUG_CACHE) { + Log.d(TAG, "keyboard cache size=" + sKeyboardCache.size() + ": " + + ((ref == null) ? "LOAD" : "GCed") + " id=" + id); + } + } else if (DEBUG_CACHE) { + Log.d(TAG, "keyboard cache size=" + sKeyboardCache.size() + ": HIT id=" + id); + } + + // TODO: Remove setShiftLocked and setShift calls. + keyboard.setShiftLocked(false); + keyboard.setShifted(false); + return keyboard; } public static class Builder { + private final Context mContext; 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 mVoiceKeyOnMain; - private final boolean mNoSettingsKey; - private final Locale mLocale; - private final Configuration mConf; - private final DisplayMetrics mMetrics; + private final Params mParams = new Params(); public Builder(Context context, EditorInfo editorInfo, SettingsValues settingsValues) { + mContext = context; mResources = context.getResources(); - mEditorInfo = editorInfo; final SubtypeSwitcher subtypeSwitcher = SubtypeSwitcher.getInstance(); final String packageName = context.getPackageName(); + final Params params = mParams; - mMode = Utils.getKeyboardMode(mEditorInfo); - mSettingsKeyEnabled = settingsValues.isSettingsKeyEnabled(); + params.mMode = Utils.getKeyboardMode(editorInfo); + if (editorInfo != null) { + params.mInputType = editorInfo.inputType; + params.mImeOptions = editorInfo.imeOptions; + } + params.mSettingsKeyEnabled = settingsValues.isSettingsKeyEnabled(); @SuppressWarnings("deprecation") final boolean noMicrophone = Utils.inPrivateImeOptions( packageName, LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo) || Utils.inPrivateImeOptions( null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo); - mVoiceKeyEnabled = settingsValues.isVoiceKeyEnabled(editorInfo) && !noMicrophone; - mVoiceKeyOnMain = settingsValues.isVoiceKeyOnMain(); - mNoSettingsKey = Utils.inPrivateImeOptions( + params.mVoiceKeyEnabled = settingsValues.isVoiceKeyEnabled(editorInfo) && !noMicrophone; + params.mVoiceKeyOnMain = settingsValues.isVoiceKeyOnMain(); + params.mNoSettingsKey = Utils.inPrivateImeOptions( packageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, editorInfo); final boolean forceAscii = Utils.inPrivateImeOptions( packageName, LatinIME.IME_OPTION_FORCE_ASCII, editorInfo); final boolean asciiCapable = subtypeSwitcher.currentSubtypeContainsExtraValueKey( LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE); - mLocale = (forceAscii && !asciiCapable) ? Locale.US : subtypeSwitcher.getInputLocale(); - mConf = mResources.getConfiguration(); - mMetrics = mResources.getDisplayMetrics(); + params.mLocale = (forceAscii && !asciiCapable) + ? Locale.US : subtypeSwitcher.getInputLocale(); + params.mOrientation = mResources.getConfiguration().orientation; + params.mWidth = mResources.getDisplayMetrics().widthPixels; } public KeyboardSet build() { - final Locale savedLocale = LocaleUtils.setSystemLocale(mResources, mLocale); + final Locale savedLocale = LocaleUtils.setSystemLocale(mResources, mParams.mLocale); try { parseKeyboardSet(mResources, R.xml.keyboard_set); } catch (Exception e) { @@ -112,19 +195,20 @@ public class KeyboardSet { } finally { LocaleUtils.setSystemLocale(mResources, savedLocale); } - return new KeyboardSet(this); + return new KeyboardSet(mContext, mParams); } - KeyboardId getKeyboardId(boolean isSymbols, boolean isShift) { - 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); + // TODO: Move this method to KeyboardSet + static KeyboardId getKeyboardId(int elementState, boolean isSymbols, Params params) { + final boolean hasShortcutKey = params.mVoiceKeyEnabled + && (isSymbols != params.mVoiceKeyOnMain); + return new KeyboardId(elementState, params.mLocale, params.mOrientation, params.mWidth, + params.mMode, params.mInputType, params.mImeOptions, params.mSettingsKeyEnabled, + params.mNoSettingsKey, params.mVoiceKeyEnabled, hasShortcutKey); } - private static int getElementState(int mode, boolean isSymbols, boolean isShift) { + // TODO: Move this method to KeyboardSet + static int getElementState(int mode, boolean isSymbols, boolean isShift) { switch (mode) { case KeyboardId.MODE_PHONE: return (isSymbols && isShift) @@ -198,7 +282,7 @@ public class KeyboardSet { R.styleable.KeyboardSet_Element_elementName, 0); final int elementKeyboard = a.getResourceId( R.styleable.KeyboardSet_Element_elementKeyboard, 0); - mElementKeyboards.put(elementName, elementKeyboard); + mParams.mElementKeyboards.put(elementName, elementKeyboard); } finally { a.recycle(); } @@ -208,7 +292,8 @@ public class KeyboardSet { public static String parseKeyboardLocale(Resources res, int resId) throws XmlPullParserException, IOException { final XmlPullParser parser = res.getXml(resId); - if (parser == null) return ""; + if (parser == null) + return ""; int event; while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { if (event == XmlPullParser.START_TAG) { diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index 3d4a6efcd..4f6d5f80f 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -31,21 +31,15 @@ import com.android.inputmethod.keyboard.internal.KeyboardState; import com.android.inputmethod.latin.InputView; import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinImeLogger; -import com.android.inputmethod.latin.LocaleUtils; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.Settings; import com.android.inputmethod.latin.SettingsValues; import com.android.inputmethod.latin.SubtypeSwitcher; import com.android.inputmethod.latin.Utils; -import java.lang.ref.SoftReference; -import java.util.HashMap; -import java.util.Locale; - public class KeyboardSwitcher implements KeyboardState.SwitchActions, SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = KeyboardSwitcher.class.getSimpleName(); - private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG; public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20110916"; private static final int[] KEYBOARD_THEMES = { @@ -69,9 +63,6 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, private KeyboardSet mKeyboardSet; - private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache = - new HashMap<KeyboardId, SoftReference<LatinKeyboard>>(); - /** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of * what user actually typed. */ private boolean mIsAutoCorrectionActive; @@ -121,25 +112,27 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, if (mThemeIndex != themeIndex) { mThemeIndex = themeIndex; mThemeContext = new ContextThemeWrapper(context, KEYBOARD_THEMES[themeIndex]); - mKeyboardCache.clear(); + KeyboardSet.clearKeyboardCache(); } } public void loadKeyboard(EditorInfo editorInfo, SettingsValues settingsValues) { + mKeyboardSet = new KeyboardSet.Builder(mThemeContext, editorInfo, settingsValues) + .build(); + final KeyboardId mainKeyboardId = mKeyboardSet.getMainKeyboardId(); try { - mKeyboardSet = new KeyboardSet.Builder(mInputMethodService, editorInfo, settingsValues) - .build(); mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols), hasDistinctMultitouch()); - // TODO: Should get rid of this special case handling for Phone Number layouts once we - // have separate layouts with unique KeyboardIds for alphabet and alphabet-shifted - // respectively. - if (mKeyboardSet.mAlphabetId.isPhoneKeyboard()) { - mState.onToggleAlphabetAndSymbols(); - } } catch (RuntimeException e) { - Log.w(TAG, "loading keyboard failed: " + mKeyboardSet.mAlphabetId, e); - LatinImeLogger.logOnException(mKeyboardSet.mAlphabetId.toString(), e); + Log.w(TAG, "loading keyboard failed: " + mainKeyboardId, e); + LatinImeLogger.logOnException(mainKeyboardId.toString(), e); + return; + } + // TODO: Should get rid of this special case handling for Phone Number layouts once we + // have separate layouts with unique KeyboardIds for alphabet and alphabet-shifted + // respectively. + if (mainKeyboardId.isPhoneKeyboard()) { + mState.onToggleAlphabetAndSymbols(); } } @@ -181,39 +174,6 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged); } - // TODO: Move this method to KeyboardSet. - private LatinKeyboard getKeyboard(Context context, KeyboardId id) { - final SoftReference<LatinKeyboard> ref = mKeyboardCache.get(id); - LatinKeyboard keyboard = (ref == null) ? null : ref.get(); - if (keyboard == null) { - final Locale savedLocale = LocaleUtils.setSystemLocale(mResources, id.mLocale); - try { - final LatinKeyboard.Builder builder = new LatinKeyboard.Builder(context); - builder.load(id); - builder.setTouchPositionCorrectionEnabled( - mSubtypeSwitcher.currentSubtypeContainsExtraValueKey( - LatinIME.SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION)); - keyboard = builder.build(); - } finally { - LocaleUtils.setSystemLocale(mResources, savedLocale); - } - mKeyboardCache.put(id, new SoftReference<LatinKeyboard>(keyboard)); - - if (DEBUG_CACHE) { - Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": " - + ((ref == null) ? "LOAD" : "GCed") + " id=" + id - + " theme=" + themeName(keyboard.mThemeId)); - } - } else if (DEBUG_CACHE) { - Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT id=" + id - + " theme=" + themeName(keyboard.mThemeId)); - } - - keyboard.setShiftLocked(false); - keyboard.setShifted(false); - return keyboard; - } - public boolean isAlphabetMode() { final Keyboard keyboard = getLatinKeyboard(); return keyboard != null && keyboard.mId.isAlphabetKeyboard(); @@ -343,25 +303,19 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, // Implements {@link KeyboardState.SwitchActions}. @Override public void setSymbolsKeyboard() { - setKeyboard(getKeyboard(mThemeContext, mKeyboardSet.mSymbolsId)); + setKeyboard(mKeyboardSet.getMainKeyboard()); } // Implements {@link KeyboardState.SwitchActions}. @Override public void setAlphabetKeyboard() { - setKeyboard(getKeyboard(mThemeContext, mKeyboardSet.mAlphabetId)); + setKeyboard(mKeyboardSet.getSymbolsKeyboard()); } // Implements {@link KeyboardState.SwitchActions}. @Override public void setSymbolsShiftedKeyboard() { - final Keyboard keyboard = getKeyboard(mThemeContext, mKeyboardSet.mSymbolsShiftedId); - setKeyboard(keyboard); - // TODO: Remove this logic once we introduce initial keyboard shift state attribute. - // Symbol shift keyboard may have a shift key that has a caps lock style indicator (a.k.a. - // sticky shift key). To show or dismiss the indicator, we need to call setShiftLocked() - // that takes care of the current keyboard having such shift key or not. - keyboard.setShiftLocked(keyboard.hasShiftLockKey()); + setKeyboard(mKeyboardSet.getSymbolsShiftedKeyboard()); } public boolean isInMomentarySwitchState() { diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java index abb96f0bb..7437e99f9 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java @@ -109,6 +109,8 @@ public class LatinKeyboard extends Keyboard { public Key mSpaceKey = null; public Key mShortcutKey = null; + LatinKeyboardParams() {} + @Override public void onAddKey(Key key) { super.onAddKey(key); @@ -130,8 +132,8 @@ public class LatinKeyboard extends Keyboard { } @Override - public Builder load(KeyboardId id) { - super.load(id); + public Builder load(int xmlId, KeyboardId id) { + super.load(xmlId, id); return this; } diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 49b8ce76f..c09541f6d 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -21,6 +21,7 @@ import android.content.pm.PackageManager; import android.content.res.Resources; import android.graphics.Canvas; import android.os.Message; +import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.view.GestureDetector; @@ -38,9 +39,11 @@ import com.android.inputmethod.deprecated.VoiceProxy; import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy; import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; import com.android.inputmethod.latin.LatinIME; +import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.StaticInnerHandlerWrapper; import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils; import java.util.WeakHashMap; @@ -62,6 +65,9 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke // Timing constants private final int mKeyRepeatInterval; + // TODO: Kill process when the usability study mode was changed. + private static final boolean ENABLE_USABILITY_STUDY_LOG = LatinImeLogger.sUsabilityStudy; + // Mini keyboard private PopupWindow mMoreKeysWindow; private MoreKeysPanel mMoreKeysPanel; @@ -513,6 +519,30 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke x = (int)me.getX(index); y = (int)me.getY(index); } + if (ENABLE_USABILITY_STUDY_LOG) { + final String eventTag; + switch (action) { + case MotionEvent.ACTION_UP: + eventTag = "[Up]"; + break; + case MotionEvent.ACTION_DOWN: + eventTag = "[Down]"; + break; + case MotionEvent.ACTION_POINTER_UP: + eventTag = "[PointerUp]"; + break; + case MotionEvent.ACTION_POINTER_DOWN: + eventTag = "[PointerDown]"; + break; + default: + eventTag = "[Action" + action + "]"; + break; + } + if (!TextUtils.isEmpty(eventTag)) { + UsabilityStudyLogUtils.getInstance().write( + eventTag + eventTime + "," + id + "," + x + "," + y + "\t\t"); + } + } if (mKeyTimerHandler.isInKeyRepeat()) { final PointerTracker tracker = getPointerTracker(id); @@ -569,6 +599,10 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke py = (int)me.getY(i); } tracker.onMoveEvent(px, py, eventTime); + if (ENABLE_USABILITY_STUDY_LOG) { + UsabilityStudyLogUtils.getInstance().write("[Move]" + eventTime + "," + + me.getPointerId(i) + "," + px + "," + py + "\t\t"); + } } } else { getPointerTracker(id).processMotionEvent(action, x, y, eventTime, this); diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java index e0f21a247..6781459d0 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(xmlId)); + load(xmlId, parentKeyboard.mId); // TODO: Mini keyboard's vertical gap is currently calculated heuristically. // Should revise the algorithm. diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java index 7382cfa7f..7ef471c93 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java @@ -267,9 +267,9 @@ public class KeyboardBuilder<KP extends KeyboardParams> { params.mTouchPositionCorrection.load(data); } - public KeyboardBuilder<KP> load(KeyboardId id) { + public KeyboardBuilder<KP> load(int xmlId, KeyboardId id) { mParams.mId = id; - final XmlResourceParser parser = mResources.getXml(id.getXmlId()); + final XmlResourceParser parser = mResources.getXml(xmlId); try { parseKeyboard(parser); } catch (XmlPullParserException e) { diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java new file mode 100644 index 000000000..c5b9703aa --- /dev/null +++ b/java/src/com/android/inputmethod/latin/InputAttributes.java @@ -0,0 +1,103 @@ +/* + * 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.latin; + +import android.text.InputType; +import android.util.Log; +import android.view.inputmethod.EditorInfo; + +import com.android.inputmethod.compat.InputTypeCompatUtils; + +/** + * Class to hold attributes of the input field. + */ +public class InputAttributes { + private final String TAG = InputAttributes.class.getSimpleName(); + + final public boolean mInsertSpaceOnPickSuggestionManually; + final public boolean mInputTypeNoAutoCorrect; + final public boolean mIsSettingsSuggestionStripOn; + final public boolean mApplicationSpecifiedCompletionOn; + + public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMode) { + if (editorInfo == null || editorInfo.inputType == InputType.TYPE_CLASS_TEXT) { + mInsertSpaceOnPickSuggestionManually = false; + mIsSettingsSuggestionStripOn = false; + mInputTypeNoAutoCorrect = false; + mApplicationSpecifiedCompletionOn = false; + } else { + final int inputType = editorInfo.inputType; + if (inputType == InputType.TYPE_NULL) { + // TODO: We should honor TYPE_NULL specification. + Log.i(TAG, "InputType.TYPE_NULL is specified"); + } + final int inputClass = inputType & InputType.TYPE_MASK_CLASS; + final int variation = inputType & InputType.TYPE_MASK_VARIATION; + if (inputClass == 0) { + // TODO: is this check still necessary? + Log.w(TAG, String.format("Unexpected input class: inputType=0x%08x" + + " imeOptions=0x%08x", + inputType, editorInfo.imeOptions)); + } + final boolean flagNoSuggestions = + 0 != (inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); + final boolean flagMultiLine = + 0 != (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE); + final boolean flagAutoCorrect = + 0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); + final boolean flagAutoComplete = + 0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE); + + // Make sure that passwords are not displayed in {@link SuggestionsView}. + if (InputTypeCompatUtils.isPasswordInputType(inputType) + || InputTypeCompatUtils.isVisiblePasswordInputType(inputType) + || InputTypeCompatUtils.isEmailVariation(variation) + || InputType.TYPE_TEXT_VARIATION_URI == variation + || InputType.TYPE_TEXT_VARIATION_FILTER == variation + || flagNoSuggestions + || flagAutoComplete) { + mIsSettingsSuggestionStripOn = false; + } else { + mIsSettingsSuggestionStripOn = true; + } + + if (InputTypeCompatUtils.isEmailVariation(variation) + || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) { + // The point in turning this off is that we don't want to insert a space after + // a name when filling a form: we can't delete trailing spaces when changing fields + mInsertSpaceOnPickSuggestionManually = false; + } else { + mInsertSpaceOnPickSuggestionManually = true; + } + + // If it's a browser edit field and auto correct is not ON explicitly, then + // disable auto correction, but keep suggestions on. + // If NO_SUGGESTIONS is set, don't do prediction. + // If it's not multiline and the autoCorrect flag is not set, then don't correct + if ((variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT + && !flagAutoCorrect) + || flagNoSuggestions + || (!flagAutoCorrect && !flagMultiLine)) { + mInputTypeNoAutoCorrect = true; + } else { + mInputTypeNoAutoCorrect = false; + } + + mApplicationSpecifiedCompletionOn = flagAutoComplete && isFullscreenMode; + } + } +} diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index a844df1bf..69fc87bc5 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -176,6 +176,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private int mSpaceState; private SettingsValues mSettingsValues; + private InputAttributes mInputAttributes; private View mExtractArea; private View mKeyPreviewBackingView; @@ -196,13 +197,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private UserUnigramDictionary mUserUnigramDictionary; private boolean mIsUserDictionaryAvailable; - // TODO: Create an inner class to group options and pseudo-options to improve readability. - // These variables are initialized according to the {@link EditorInfo#inputType}. - private boolean mInsertSpaceOnPickSuggestionManually; - private boolean mInputTypeNoAutoCorrect; - private boolean mIsSettingsSuggestionStripOn; - private boolean mApplicationSpecifiedCompletionOn; - private WordComposer mWordComposer = new WordComposer(); private boolean mHasUncommittedTypedChars; @@ -515,6 +509,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar loadSettings(); + // TODO: remove the following when it's not needed by updateCorrectionMode() any more + mInputAttributes = new InputAttributes(null, false /* isFullscreenMode */); Utils.GCUtils.getInstance().reset(); boolean tryGC = true; for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { @@ -757,7 +753,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // The EditorInfo might have a flag that affects fullscreen mode. // Note: This call should be done by InputMethodService? updateFullscreenMode(); - initializeInputAttributes(editorInfo); + mInputAttributes = new InputAttributes(editorInfo, isFullscreenMode()); + mApplicationSpecifiedCompletions = null; inputView.closing(); mEnteredText = null; @@ -798,73 +795,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); } - private void initializeInputAttributes(EditorInfo editorInfo) { - if (editorInfo == null) - return; - final int inputType = editorInfo.inputType; - if (inputType == InputType.TYPE_NULL) { - // TODO: We should honor TYPE_NULL specification. - Log.i(TAG, "InputType.TYPE_NULL is specified"); - } - final int inputClass = inputType & InputType.TYPE_MASK_CLASS; - final int variation = inputType & InputType.TYPE_MASK_VARIATION; - if (inputClass == 0) { - Log.w(TAG, String.format("Unexpected input class: inputType=0x%08x imeOptions=0x%08x", - inputType, editorInfo.imeOptions)); - } - - mInsertSpaceOnPickSuggestionManually = false; - mInputTypeNoAutoCorrect = false; - mIsSettingsSuggestionStripOn = false; - mApplicationSpecifiedCompletionOn = false; - mApplicationSpecifiedCompletions = null; - - if (inputClass == InputType.TYPE_CLASS_TEXT) { - mIsSettingsSuggestionStripOn = true; - // Make sure that passwords are not displayed in {@link SuggestionsView}. - if (InputTypeCompatUtils.isPasswordInputType(inputType) - || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)) { - mIsSettingsSuggestionStripOn = false; - } - if (InputTypeCompatUtils.isEmailVariation(variation) - || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) { - // The point in turning this off is that we don't want to insert a space after - // a name when filling a form: we can't delete trailing spaces when changing fields - mInsertSpaceOnPickSuggestionManually = false; - } else { - mInsertSpaceOnPickSuggestionManually = true; - } - if (InputTypeCompatUtils.isEmailVariation(variation)) { - mIsSettingsSuggestionStripOn = false; - } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) { - mIsSettingsSuggestionStripOn = false; - } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) { - mIsSettingsSuggestionStripOn = false; - } else if (variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) { - // If it's a browser edit field and auto correct is not ON explicitly, then - // disable auto correction, but keep suggestions on. - if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) { - mInputTypeNoAutoCorrect = true; - } - } - - // If NO_SUGGESTIONS is set, don't do prediction. - if ((inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) { - mIsSettingsSuggestionStripOn = false; - mInputTypeNoAutoCorrect = true; - } - // If it's not multiline and the autoCorrect flag is not set, then don't correct - if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 - && (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { - mInputTypeNoAutoCorrect = true; - } - if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { - mIsSettingsSuggestionStripOn = false; - mApplicationSpecifiedCompletionOn = isFullscreenMode(); - } - } - } - @Override public void onWindowHidden() { super.onWindowHidden(); @@ -1016,7 +946,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } } - if (mApplicationSpecifiedCompletionOn) { + if (mInputAttributes.mApplicationSpecifiedCompletionOn) { mApplicationSpecifiedCompletions = applicationSpecifiedCompletions; if (applicationSpecifiedCompletions == null) { clearSuggestions(); @@ -1612,7 +1542,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // in Italian dov' should not be expanded to dove' because the elision // requires the last vowel to be removed. final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled - && !mInputTypeNoAutoCorrect; + && !mInputAttributes.mInputTypeNoAutoCorrect; if (shouldAutoCorrect && primaryCode != Keyboard.CODE_SINGLE_QUOTE) { commitCurrentAutoCorrection(primaryCode, ic); } else { @@ -1689,7 +1619,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } public boolean isSuggestionsRequested() { - return mIsSettingsSuggestionStripOn + return mInputAttributes.mIsSettingsSuggestionStripOn && (mCorrectionMode > 0 || isShowingSuggestionsStrip()); } @@ -1711,7 +1641,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return true; if (!isShowingSuggestionsStrip()) return false; - if (mApplicationSpecifiedCompletionOn) + if (mInputAttributes.mApplicationSpecifiedCompletionOn) return true; return isSuggestionsRequested(); } @@ -1798,7 +1728,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(mWordComposer, prevWord, mKeyboardSwitcher.getLatinKeyboard().getProximityInfo(), mCorrectionMode); - boolean autoCorrectionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasAutoCorrection(); + boolean autoCorrectionAvailable = !mInputAttributes.mInputTypeNoAutoCorrect + && mSuggest.hasAutoCorrection(); 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" @@ -1914,7 +1845,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (ic != null) { ic.beginBatchEdit(); } - if (mApplicationSpecifiedCompletionOn && mApplicationSpecifiedCompletions != null + if (mInputAttributes.mApplicationSpecifiedCompletionOn + && mApplicationSpecifiedCompletions != null && index >= 0 && index < mApplicationSpecifiedCompletions.length) { if (ic != null) { final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index]; @@ -1968,7 +1900,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar LatinImeLogger.logOnManualSuggestion(mWordComposer.getTypedWord().toString(), suggestion.toString(), index, suggestions.mWords); // Follow it with a space - if (mInsertSpaceOnPickSuggestionManually) { + if (mInputAttributes.mInsertSpaceOnPickSuggestionManually) { sendMagicSpace(); } @@ -2419,7 +2351,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private void updateCorrectionMode() { // TODO: cleanup messy flags final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled - && !mInputTypeNoAutoCorrect; + && !mInputAttributes.mInputTypeNoAutoCorrect; mCorrectionMode = shouldAutoCorrect ? Suggest.CORRECTION_FULL : Suggest.CORRECTION_NONE; mCorrectionMode = (mSettingsValues.mBigramSuggestionEnabled && shouldAutoCorrect) ? Suggest.CORRECTION_FULL_BIGRAM : mCorrectionMode; @@ -2518,12 +2450,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final Keyboard keyboard = mKeyboardSwitcher.getLatinKeyboard(); final int keyboardMode = keyboard != null ? keyboard.mId.mMode : -1; p.println(" Keyboard mode = " + keyboardMode); - p.println(" mIsSuggestionsRequested=" + mIsSettingsSuggestionStripOn); + p.println(" mIsSuggestionsRequested=" + mInputAttributes.mIsSettingsSuggestionStripOn); p.println(" mCorrectionMode=" + mCorrectionMode); p.println(" mHasUncommittedTypedChars=" + mHasUncommittedTypedChars); p.println(" mAutoCorrectEnabled=" + mSettingsValues.mAutoCorrectEnabled); - p.println(" mInsertSpaceOnPickSuggestionManually=" + mInsertSpaceOnPickSuggestionManually); - p.println(" mApplicationSpecifiedCompletionOn=" + mApplicationSpecifiedCompletionOn); + p.println(" mInsertSpaceOnPickSuggestionManually=" + + mInputAttributes.mInsertSpaceOnPickSuggestionManually); + p.println(" mApplicationSpecifiedCompletionOn=" + + mInputAttributes.mApplicationSpecifiedCompletionOn); p.println(" mSoundOn=" + mSettingsValues.mSoundOn); p.println(" mVibrateOn=" + mSettingsValues.mVibrateOn); p.println(" mKeyPreviewPopupOn=" + mSettingsValues.mKeyPreviewPopupOn); diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java index da5058dd4..6f1adfe71 100644 --- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java +++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java @@ -29,6 +29,7 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang public static boolean sDBG = false; public static boolean sVISUALDEBUG = false; + public static boolean sUsabilityStudy = false; @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java index 7f5918991..eeabb30e4 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java @@ -181,7 +181,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(xmlId)); + load(xmlId, keyboard.mId); mParams.mVerticalGap = mParams.mTopPadding = keyboard.mVerticalGap / 2; final int count = mParams.layout(suggestions, fromPos, maxWidth, minWidth, maxRow, |