diff options
Diffstat (limited to 'java/src')
15 files changed, 257 insertions, 171 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index cf3a437cf..f839376c0 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -105,6 +105,9 @@ public class Key { public final String[] mMoreKeys; /** More keys maximum column number */ public final int mMaxMoreKeysColumn; + public static final int MORE_KEYS_FIXED_COLUMN_ORDER = 0x80000000; + private static final String AUTO_COLUMN_ORDER = "!autoColumnOrder!"; + private static final String FIXED_COLUMN_ORDER = "!fixedColumnOrder!"; /** Background type that represents different key background visual than normal one. */ public final int mBackgroundType; @@ -232,10 +235,19 @@ public class Key { mLabelFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags); final boolean preserveCase = (mLabelFlags & LABEL_FLAGS_PRESERVE_CASE) != 0; int actionFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyActionFlags); + String[] moreKeys = style.getStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys); + int column; + if ((column = parseMoreKeysColumnOrder(moreKeys, AUTO_COLUMN_ORDER)) > 0) { + mMaxMoreKeysColumn = column; + } else if ((column = parseMoreKeysColumnOrder(moreKeys, FIXED_COLUMN_ORDER)) > 0) { + mMaxMoreKeysColumn = column | MORE_KEYS_FIXED_COLUMN_ORDER; + } else { + mMaxMoreKeysColumn = style.getInt(keyAttr, + R.styleable.Keyboard_Key_maxMoreKeysColumn, params.mMaxMoreKeysKeyboardColumn); + } final String[] additionalMoreKeys = style.getStringArray( keyAttr, R.styleable.Keyboard_Key_additionalMoreKeys); - final String[] moreKeys = KeySpecParser.insertAddtionalMoreKeys(style.getStringArray( - keyAttr, R.styleable.Keyboard_Key_moreKeys), additionalMoreKeys); + moreKeys = KeySpecParser.insertAddtionalMoreKeys(moreKeys, additionalMoreKeys); if (moreKeys != null) { actionFlags |= ACTION_FLAGS_ENABLE_LONG_PRESS; for (int i = 0; i < moreKeys.length; i++) { @@ -245,8 +257,6 @@ public class Key { } mActionFlags = actionFlags; mMoreKeys = moreKeys; - mMaxMoreKeysColumn = style.getInt(keyAttr, - R.styleable.Keyboard_Key_maxMoreKeysColumn, params.mMaxMoreKeysKeyboardColumn); if ((mLabelFlags & LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL) != 0) { mLabel = params.mId.mCustomActionLabel; @@ -301,6 +311,21 @@ public class Key { } } + private static int parseMoreKeysColumnOrder(String[] moreKeys, String key) { + if (moreKeys == null || moreKeys.length == 0 || moreKeys[0] == null + || !moreKeys[0].startsWith(key)) { + return -1; + } + try { + final int column = Integer.parseInt(moreKeys[0].substring(key.length())); + moreKeys[0] = null; + return column; + } catch (NumberFormatException e) { + Log.w(TAG, "column number should follow after " + key); + return 0; + } + } + private static int adjustCaseOfCodeForKeyboardId(int code, boolean preserveCase, KeyboardId id) { if (!Keyboard.isLetterCode(code) || preserveCase) return code; diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java index bff491ffd..0ce98d2f1 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java +++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java @@ -180,32 +180,34 @@ public class KeyDetector { if (maxCodesSize <= numCodes) { return; } - if (primaryCode != NOT_A_CODE) { - final List<Integer> additionalChars = - mKeyboard.getAdditionalProximityChars().get(primaryCode); - if (additionalChars == null || additionalChars.size() == 0) { - return; - } - int currentCodesSize = numCodes; - allCodes[numCodes++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE; - if (maxCodesSize <= numCodes) { - return; - } - // TODO: This is O(N^2). Assuming additionalChars.size() is up to 4 or 5. - for (int i = 0; i < additionalChars.size(); ++i) { - final int additionalChar = additionalChars.get(i); - boolean contains = false; - for (int j = 0; j < currentCodesSize; ++j) { - if (additionalChar == allCodes[j]) { - contains = true; - break; - } + + final int code = (primaryCode == NOT_A_CODE) ? allCodes[0] : primaryCode; + if (code == NOT_A_CODE) { + return; + } + final List<Integer> additionalChars = mKeyboard.getAdditionalProximityChars().get(code); + if (additionalChars == null || additionalChars.size() == 0) { + return; + } + int currentCodesSize = numCodes; + allCodes[numCodes++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE; + if (maxCodesSize <= numCodes) { + return; + } + // TODO: This is O(N^2). Assuming additionalChars.size() is up to 4 or 5. + for (int i = 0; i < additionalChars.size(); ++i) { + final int additionalChar = additionalChars.get(i); + boolean contains = false; + for (int j = 0; j < currentCodesSize; ++j) { + if (additionalChar == allCodes[j]) { + contains = true; + break; } - if (!contains) { - allCodes[numCodes++] = additionalChar; - if (maxCodesSize <= numCodes) { - return; - } + } + if (!contains) { + allCodes[numCodes++] = additionalChar; + if (maxCodesSize <= numCodes) { + return; } } } @@ -257,10 +259,17 @@ public class KeyDetector { public static String printableCodes(int[] codes) { final StringBuilder sb = new StringBuilder(); + boolean addDelimiter = false; for (final int code : codes) { if (code == NOT_A_CODE) break; - if (sb.length() > 0) sb.append(", "); - sb.append(code); + if (code == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { + sb.append(" | "); + addDelimiter = false; + } else { + if (addDelimiter) sb.append(", "); + sb.append(code); + addDelimiter = true; + } } return "[" + sb + "]"; } diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index 28f71f443..60e506914 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -1073,10 +1073,6 @@ public class Keyboard { R.styleable.Keyboard_Case_navigateAction, id.navigateAction()); final boolean passwordInputMatched = matchBoolean(a, R.styleable.Keyboard_Case_passwordInput, id.passwordInput()); - final boolean hasSettingsKeyMatched = matchBoolean(a, - R.styleable.Keyboard_Case_hasSettingsKey, id.hasSettingsKey()); - final boolean f2KeyModeMatched = matchInteger(a, - R.styleable.Keyboard_Case_f2KeyMode, id.f2KeyMode()); final boolean clobberSettingsKeyMatched = matchBoolean(a, R.styleable.Keyboard_Case_clobberSettingsKey, id.mClobberSettingsKey); final boolean shortcutKeyEnabledMatched = matchBoolean(a, @@ -1094,14 +1090,13 @@ public class Keyboard { final boolean countryCodeMatched = matchString(a, R.styleable.Keyboard_Case_countryCode, id.mLocale.getCountry()); final boolean selected = keyboardSetElementMatched && modeMatched - && navigateActionMatched && passwordInputMatched && hasSettingsKeyMatched - && f2KeyModeMatched && clobberSettingsKeyMatched - && shortcutKeyEnabledMatched && hasShortcutKeyMatched && isMultiLineMatched - && imeActionMatched && localeCodeMatched && languageCodeMatched - && countryCodeMatched; + && navigateActionMatched && passwordInputMatched + && clobberSettingsKeyMatched && shortcutKeyEnabledMatched + && hasShortcutKeyMatched && isMultiLineMatched && imeActionMatched + && localeCodeMatched && languageCodeMatched && countryCodeMatched; if (DEBUG) { - startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE, + startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE, textAttr(a.getString(R.styleable.Keyboard_Case_keyboardSetElement), "keyboardSetElement"), textAttr(a.getString(R.styleable.Keyboard_Case_mode), "mode"), @@ -1109,11 +1104,6 @@ public class Keyboard { "navigateAction"), booleanAttr(a, R.styleable.Keyboard_Case_passwordInput, "passwordInput"), - booleanAttr(a, R.styleable.Keyboard_Case_hasSettingsKey, - "hasSettingsKey"), - textAttr(KeyboardId.f2KeyModeName( - a.getInt(R.styleable.Keyboard_Case_f2KeyMode, -1)), - "f2KeyMode"), booleanAttr(a, R.styleable.Keyboard_Case_clobberSettingsKey, "clobberSettingsKey"), booleanAttr(a, R.styleable.Keyboard_Case_shortcutKeyEnabled, diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java index 3ab24933c..a75caf262 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java @@ -48,11 +48,6 @@ public class KeyboardId { public static final int ELEMENT_PHONE_SYMBOLS = 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; - private static final int IME_ACTION_CUSTOM_LABEL = EditorInfo.IME_MASK_ACTION + 1; public final Locale mLocale; @@ -61,7 +56,6 @@ public class KeyboardId { public final int mMode; public final int mElementId; private final EditorInfo mEditorInfo; - private final boolean mSettingsKeyEnabled; public final boolean mClobberSettingsKey; public final boolean mShortcutKeyEnabled; public final boolean mHasShortcutKey; @@ -70,15 +64,14 @@ public class KeyboardId { private final int mHashCode; public KeyboardId(int elementId, Locale locale, int orientation, int width, int mode, - EditorInfo editorInfo, boolean settingsKeyEnabled, boolean clobberSettingsKey, - boolean shortcutKeyEnabled, boolean hasShortcutKey) { + EditorInfo editorInfo, boolean clobberSettingsKey, boolean shortcutKeyEnabled, + boolean hasShortcutKey) { this.mLocale = locale; this.mOrientation = orientation; this.mWidth = width; this.mMode = mode; this.mElementId = elementId; this.mEditorInfo = editorInfo; - this.mSettingsKeyEnabled = settingsKeyEnabled; this.mClobberSettingsKey = clobberSettingsKey; this.mShortcutKeyEnabled = shortcutKeyEnabled; this.mHasShortcutKey = hasShortcutKey; @@ -96,7 +89,6 @@ public class KeyboardId { id.mWidth, id.navigateAction(), id.passwordInput(), - id.mSettingsKeyEnabled, id.mClobberSettingsKey, id.mShortcutKeyEnabled, id.mHasShortcutKey, @@ -116,7 +108,6 @@ public class KeyboardId { && other.mWidth == this.mWidth && other.navigateAction() == this.navigateAction() && other.passwordInput() == this.passwordInput() - && other.mSettingsKeyEnabled == this.mSettingsKeyEnabled && other.mClobberSettingsKey == this.mClobberSettingsKey && other.mShortcutKeyEnabled == this.mShortcutKeyEnabled && other.mHasShortcutKey == this.mHasShortcutKey @@ -183,25 +174,6 @@ public class KeyboardId { } } - 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 public boolean equals(Object other) { return other instanceof KeyboardId && equals((KeyboardId) other); @@ -214,17 +186,15 @@ public class KeyboardId { @Override public String toString() { - return String.format("[%s %s %s%d %s %s %s%s%s%s%s%s%s]", + return String.format("[%s %s %s%d %s %s %s%s%s%s%s]", elementIdToName(mElementId), mLocale, (mOrientation == 1 ? "port" : "land"), mWidth, modeName(mMode), imeAction(), - f2KeyModeName(f2KeyMode()), (mClobberSettingsKey ? " clobberSettingsKey" : ""), (navigateAction() ? " navigateAction" : ""), (passwordInput() ? " passwordInput" : ""), - (hasSettingsKey() ? " hasSettingsKey" : ""), (mShortcutKeyEnabled ? " shortcutKeyEnabled" : ""), (mHasShortcutKey ? " hasShortcutKey" : "") ); @@ -270,14 +240,4 @@ public class KeyboardId { return (actionId == IME_ACTION_CUSTOM_LABEL) ? "actionCustomLabel" : EditorInfoCompatUtils.imeActionName(actionId); } - - public static String f2KeyModeName(int f2KeyMode) { - switch (f2KeyMode) { - case F2KEY_MODE_NONE: return "none"; - case F2KEY_MODE_SETTINGS: return "settings"; - case F2KEY_MODE_SHORTCUT_IME: return "shortcutIme"; - case F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS: return "shortcutImeOrSettings"; - default: return null; - } - } } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java index f27170a89..6e62f743b 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java @@ -98,7 +98,6 @@ public class KeyboardSet { int mMode; EditorInfo mEditorInfo; boolean mTouchPositionCorrectionEnabled; - boolean mSettingsKeyEnabled; boolean mVoiceKeyEnabled; boolean mVoiceKeyOnMain; boolean mNoSettingsKey; @@ -193,8 +192,8 @@ public class KeyboardSet { final boolean hasShortcutKey = params.mVoiceKeyEnabled && (isSymbols != params.mVoiceKeyOnMain); return new KeyboardId(keyboardSetElementId, params.mLocale, params.mOrientation, - params.mWidth, params.mMode, params.mEditorInfo, params.mSettingsKeyEnabled, - params.mNoSettingsKey, params.mVoiceKeyEnabled, hasShortcutKey); + params.mWidth, params.mMode, params.mEditorInfo, params.mNoSettingsKey, + params.mVoiceKeyEnabled, hasShortcutKey); } public static class Builder { @@ -237,9 +236,7 @@ public class KeyboardSet { return this; } - public Builder setOptions(boolean settingsKeyEnabled, boolean voiceKeyEnabled, - boolean voiceKeyOnMain) { - mParams.mSettingsKeyEnabled = settingsKeyEnabled; + public Builder setOptions(boolean voiceKeyEnabled, boolean voiceKeyOnMain) { @SuppressWarnings("deprecation") final boolean deprecatedNoMicrophone = Utils.inPrivateImeOptions( null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, mEditorInfo); diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index 5ba560d72..622e5831f 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -35,7 +35,6 @@ import com.android.inputmethod.latin.InputView; import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinImeLogger; 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; @@ -133,7 +132,6 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, mSubtypeSwitcher.currentSubtypeContainsExtraValueKey( LatinIME.SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION)); builder.setOptions( - settingsValues.isSettingsKeyEnabled(), settingsValues.isVoiceKeyEnabled(editorInfo), settingsValues.isVoiceKeyOnMain()); mKeyboardSet = builder.build(); @@ -268,6 +266,16 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, // Implements {@link KeyboardState.SwitchActions}. @Override + public void cancelDoubleTapTimer() { + final LatinKeyboardView keyboardView = getKeyboardView(); + if (keyboardView != null) { + final TimerProxy timer = keyboardView.getTimerProxy(); + timer.cancelDoubleTapTimer(); + } + } + + // Implements {@link KeyboardState.SwitchActions}. + @Override public boolean isInDoubleTapTimeout() { final LatinKeyboardView keyboardView = getKeyboardView(); return (keyboardView != null) @@ -286,6 +294,16 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, // Implements {@link KeyboardState.SwitchActions}. @Override + public void cancelLongPressTimer() { + final LatinKeyboardView keyboardView = getKeyboardView(); + if (keyboardView != null) { + final TimerProxy timer = keyboardView.getTimerProxy(); + timer.cancelLongPressTimer(); + } + } + + // Implements {@link KeyboardState.SwitchActions}. + @Override public void hapticAndAudioFeedback(int code) { mInputMethodService.hapticAndAudioFeedback(code); } @@ -384,8 +402,6 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, if (PREF_KEYBOARD_LAYOUT.equals(key)) { final int themeIndex = getKeyboardThemeIndex(mInputMethodService, sharedPreferences); postSetInputView(createInputView(themeIndex, false)); - } else if (Settings.PREF_SHOW_SETTINGS_KEY.equals(key)) { - postSetInputView(createInputView(mThemeIndex, true)); } } diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 88a41579d..9a0fe1efa 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -233,6 +233,11 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke } @Override + public void cancelDoubleTapTimer() { + removeMessages(MSG_DOUBLE_TAP); + } + + @Override public boolean isInDoubleTapTimeout() { return hasMessages(MSG_DOUBLE_TAP); } diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java index 1597b1ebb..7d8181dda 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java @@ -37,9 +37,11 @@ public class MoreKeysKeyboard extends Keyboard { private final String[] mMoreKeys; public static class MoreKeysKeyboardParams extends Keyboard.Params { + public boolean mIsFixedOrder; /* package */int mTopRowAdjustment; public int mNumRows; public int mNumColumns; + public int mTopKeys; public int mLeftKeys; public int mRightKeys; // includes default key. @@ -58,14 +60,17 @@ public class MoreKeysKeyboard extends Keyboard { * Set keyboard parameters of more keys keyboard. * * @param numKeys number of keys in this more keys keyboard. - * @param maxColumns number of maximum columns of this more keys keyboard. + * @param maxColumnsAndFlags number of maximum columns of this more keys keyboard. + * This might have {@link Key#MORE_KEYS_FIXED_COLUMN_ORDER} flag. * @param keyWidth more keys keyboard key width in pixel, including horizontal gap. * @param rowHeight more keys keyboard row height in pixel, including vertical gap. * @param coordXInParent coordinate x of the key preview in parent keyboard. * @param parentKeyboardWidth parent keyboard width in pixel. */ - public void setParameters(int numKeys, int maxColumns, int keyWidth, int rowHeight, - int coordXInParent, int parentKeyboardWidth) { + public void setParameters(int numKeys, int maxColumnsAndFlags, int keyWidth, + int rowHeight, int coordXInParent, int parentKeyboardWidth) { + mIsFixedOrder = (maxColumnsAndFlags & Key.MORE_KEYS_FIXED_COLUMN_ORDER) != 0; + final int maxColumns = maxColumnsAndFlags & ~Key.MORE_KEYS_FIXED_COLUMN_ORDER; if (parentKeyboardWidth / keyWidth < maxColumns) { throw new IllegalArgumentException( "Keyboard is too small to hold more keys keyboard: " @@ -76,8 +81,11 @@ public class MoreKeysKeyboard extends Keyboard { final int numRows = (numKeys + maxColumns - 1) / maxColumns; mNumRows = numRows; - final int numColumns = getOptimizedColumns(numKeys, maxColumns); + final int numColumns = mIsFixedOrder ? Math.min(numKeys, maxColumns) + : getOptimizedColumns(numKeys, maxColumns); mNumColumns = numColumns; + final int topKeys = numKeys % numColumns; + mTopKeys = topKeys == 0 ? numColumns : topKeys; final int numLeftKeys = (numColumns - 1) / 2; final int numRightKeys = numColumns - numLeftKeys; // including default key. @@ -110,28 +118,68 @@ public class MoreKeysKeyboard extends Keyboard { mLeftKeys = leftKeys; mRightKeys = rightKeys; - // Centering of the top row. - if (numRows < 2 || getTopRowEmptySlots(numKeys, numColumns) % 2 == 0) { - mTopRowAdjustment = 0; - } else if (mLeftKeys < mRightKeys - 1) { - mTopRowAdjustment = 1; - } else { - mTopRowAdjustment = -1; - } - + // Adjustment of the top row. + mTopRowAdjustment = mIsFixedOrder ? getFixedOrderTopRowAdjustment() + : getAutoOrderTopRowAdjustment(); mBaseWidth = mOccupiedWidth = mNumColumns * mDefaultKeyWidth; // Need to subtract the bottom row's gutter only. mBaseHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight - mVerticalGap + mTopPadding + mBottomPadding; } + private int getFixedOrderTopRowAdjustment() { + if (mNumRows == 1 || mTopKeys % 2 == 1 || mTopKeys == mNumColumns + || mLeftKeys == 0 || mRightKeys == 1) { + return 0; + } + return -1; + } + + private int getAutoOrderTopRowAdjustment() { + if (mNumRows == 1 || mTopKeys == 1 || mNumColumns % 2 == mTopKeys % 2 + || mLeftKeys == 0 || mRightKeys == 1) { + return 0; + } + return -1; + } + // Return key position according to column count (0 is default). /* package */int getColumnPos(int n) { + return mIsFixedOrder ? getFixedOrderColumnPos(n) : getAutomaticColumnPos(n); + } + + private int getFixedOrderColumnPos(int n) { + final int col = n % mNumColumns; + final int row = n / mNumColumns; + if (!isTopRow(row)) { + return col - mLeftKeys; + } + final int rightSideKeys = mTopKeys / 2; + final int leftSideKeys = mTopKeys - (rightSideKeys + 1); + final int pos = col - leftSideKeys; + final int numLeftKeys = mLeftKeys + mTopRowAdjustment; + final int numRightKeys = mRightKeys - 1; + if (numRightKeys >= rightSideKeys && numLeftKeys >= leftSideKeys) { + return pos; + } else if (numRightKeys < rightSideKeys) { + return pos - (rightSideKeys - numRightKeys); + } else { // numLeftKeys < leftSideKeys + return pos + (leftSideKeys - numLeftKeys); + } + } + + private int getAutomaticColumnPos(int n) { final int col = n % mNumColumns; + final int row = n / mNumColumns; + int leftKeys = mLeftKeys; + if (isTopRow(row)) { + leftKeys += mTopRowAdjustment; + } if (col == 0) { // default position. return 0; } + int pos = 0; int right = 1; // include default position key. int left = 0; @@ -146,7 +194,7 @@ public class MoreKeysKeyboard extends Keyboard { if (i >= col) break; // Assign left key if available. - if (left < mLeftKeys) { + if (left < leftKeys) { left++; pos = -left; i++; @@ -158,12 +206,8 @@ public class MoreKeysKeyboard extends Keyboard { } private static int getTopRowEmptySlots(int numKeys, int numColumns) { - final int remainingKeys = numKeys % numColumns; - if (remainingKeys == 0) { - return 0; - } else { - return numColumns - remainingKeys; - } + final int remainings = numKeys % numColumns; + return remainings == 0 ? 0 : numColumns - remainings; } private int getOptimizedColumns(int numKeys, int maxColumns) { @@ -198,7 +242,7 @@ public class MoreKeysKeyboard extends Keyboard { } private boolean isTopRow(int rowCount) { - return rowCount == mNumRows - 1; + return mNumRows > 1 && rowCount == mNumRows - 1; } } diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 110f7f6ae..c45308419 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -77,6 +77,7 @@ public class PointerTracker { public void startLongPressTimer(int code); public void cancelLongPressTimer(); public void startDoubleTapTimer(); + public void cancelDoubleTapTimer(); public boolean isInDoubleTapTimeout(); public void cancelKeyTimers(); @@ -96,6 +97,8 @@ public class PointerTracker { @Override public void startDoubleTapTimer() {} @Override + public void cancelDoubleTapTimer() {} + @Override public boolean isInDoubleTapTimeout() { return false; } @Override public void cancelKeyTimers() {} diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java index 1626a140b..f61eefda5 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java @@ -206,9 +206,51 @@ public class KeySpecParser { return KeyboardIconsSet.ICON_UNDEFINED; } - public static String[] insertAddtionalMoreKeys(String[] moreKeys, String[] additionalMoreKeys) { - final int moreKeysCount = (moreKeys != null) ? moreKeys.length : 0; - final int additionalCount = (additionalMoreKeys != null) ? additionalMoreKeys.length : 0; + private static <T> ArrayList<T> arrayAsList(T[] array, int start, int end) { + if (array == null) { + throw new NullPointerException(); + } + if (start < 0 || start > end || end > array.length) { + throw new IllegalArgumentException(); + } + + final ArrayList<T> list = new ArrayList<T>(end - start); + for (int i = start; i < end; i++) { + list.add(array[i]); + } + return list; + } + + private static final String[] EMPTY_STRING_ARRAY = new String[0]; + + private static String[] filterOutEmptyString(String[] array) { + if (array == null) { + return EMPTY_STRING_ARRAY; + } + ArrayList<String> out = null; + for (int i = 0; i < array.length; i++) { + final String entry = array[i]; + if (TextUtils.isEmpty(entry)) { + if (out == null) { + out = arrayAsList(array, 0, i); + } + } else if (out != null) { + out.add(entry); + } + } + if (out == null) { + return array; + } else { + return out.toArray(new String[out.size()]); + } + } + + public static String[] insertAddtionalMoreKeys(String[] moreKeySpecs, + String[] additionalMoreKeySpecs) { + final String[] moreKeys = filterOutEmptyString(moreKeySpecs); + final String[] additionalMoreKeys = filterOutEmptyString(additionalMoreKeySpecs); + final int moreKeysCount = moreKeys.length; + final int additionalCount = additionalMoreKeys.length; ArrayList<String> out = null; int additionalIndex = 0; for (int moreKeyIndex = 0; moreKeyIndex < moreKeysCount; moreKeyIndex++) { @@ -226,10 +268,7 @@ public class KeySpecParser { } else { // Filter out excessive '%' marker. if (out == null) { - out = new ArrayList<String>(moreKeyIndex); - for (int i = 0; i < moreKeyIndex; i++) { - out.add(moreKeys[i]); - } + out = arrayAsList(moreKeys, 0, moreKeyIndex); } } } else { @@ -246,10 +285,7 @@ public class KeySpecParser { + " moreKeys=" + Arrays.toString(moreKeys) + " additionalMoreKeys=" + Arrays.toString(additionalMoreKeys)); } - out = new ArrayList<String>(additionalCount + moreKeysCount); - for (int i = additionalIndex; i < additionalCount; i++) { - out.add(additionalMoreKeys[i]); - } + out = arrayAsList(additionalMoreKeys, additionalIndex, additionalCount); for (int i = 0; i < moreKeysCount; i++) { out.add(moreKeys[i]); } @@ -261,18 +297,17 @@ public class KeySpecParser { + " moreKeys=" + Arrays.toString(moreKeys) + " additionalMoreKeys=" + Arrays.toString(additionalMoreKeys)); } - out = new ArrayList<String>(moreKeysCount); - for (int i = 0; i < moreKeysCount; i++) { - out.add(moreKeys[i]); - } + out = arrayAsList(moreKeys, 0, moreKeysCount); for (int i = additionalIndex; i < additionalCount; i++) { out.add(additionalMoreKeys[additionalIndex]); } } - if (out != null) { - return out.size() > 0 ? out.toArray(new String[out.size()]) : null; - } else { + if (out == null && moreKeysCount > 0) { return moreKeys; + } else if (out != null && out.size() > 0) { + return out.toArray(new String[out.size()]); + } else { + return null; } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java index cb8b4f05c..6a8a03677 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -54,7 +54,9 @@ public class KeyboardState { public void startDoubleTapTimer(); public boolean isInDoubleTapTimeout(); + public void cancelDoubleTapTimer(); public void startLongPressTimer(int code); + public void cancelLongPressTimer(); public void hapticAndAudioFeedback(int code); } @@ -300,6 +302,8 @@ public class KeyboardState { } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { onPressSymbol(); } else { + mSwitchActions.cancelDoubleTapTimer(); + mSwitchActions.cancelLongPressTimer(); mShiftKeyState.onOtherKeyPressed(); mSymbolKeyState.onOtherKeyPressed(); } @@ -348,7 +352,7 @@ public class KeyboardState { // state. And mark as if shift key is released. mShiftKeyState.onRelease(); } else { - // Shift key is long pressed while shift unloked state. + // Shift key is long pressed while shift unlocked state. setShiftLocked(true); } mSwitchActions.hapticAndAudioFeedback(code); @@ -364,6 +368,11 @@ public class KeyboardState { private void updateAlphabetShiftState(boolean autoCaps) { if (!mIsAlphabetMode) return; + if (!mShiftKeyState.isReleasing()) { + // Ignore update shift state event while the shift key is being pressed (including + // chording). + return; + } if (!mAlphabetShiftState.isShiftLocked() && !mShiftKeyState.isIgnoring()) { if (mShiftKeyState.isReleasing() && autoCaps) { // Only when shift key is releasing, automatic temporary upper case will be set. diff --git a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java index d9181f786..5db65c660 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java +++ b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java @@ -16,12 +16,18 @@ package com.android.inputmethod.keyboard.internal; +import android.util.Log; + +import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.PointerTracker; import java.util.Iterator; import java.util.LinkedList; public class PointerTrackerQueue { + private static final String TAG = PointerTrackerQueue.class.getSimpleName(); + private static final boolean DEBUG = false; + private final LinkedList<PointerTracker> mQueue = new LinkedList<PointerTracker>(); public synchronized void add(PointerTracker tracker) { @@ -32,7 +38,11 @@ public class PointerTrackerQueue { mQueue.remove(tracker); } - public synchronized void releaseAllPointersOlderThan(PointerTracker tracker, long eventTime) { + public synchronized void releaseAllPointersOlderThan(PointerTracker tracker, + long eventTime) { + if (DEBUG) { + Log.d(TAG, "releaseAllPoniterOlderThan: [" + tracker.mPointerId + "] " + this); + } if (!mQueue.contains(tracker)) { return; } @@ -54,6 +64,13 @@ public class PointerTrackerQueue { } public synchronized void releaseAllPointersExcept(PointerTracker tracker, long eventTime) { + if (DEBUG) { + if (tracker == null) { + Log.d(TAG, "releaseAllPoniters: " + this); + } else { + Log.d(TAG, "releaseAllPoniterExcept: [" + tracker.mPointerId + "] " + this); + } + } final Iterator<PointerTracker> it = mQueue.iterator(); while (it.hasNext()) { final PointerTracker t = it.next(); @@ -79,8 +96,9 @@ public class PointerTrackerQueue { for (final PointerTracker tracker : mQueue) { if (sb.length() > 0) sb.append(" "); - sb.append(tracker.mPointerId); + sb.append("[" + tracker.mPointerId + " " + + Keyboard.printableCode(tracker.getKey().mCode) + "]"); } - return "[" + sb + "]"; + return sb.toString(); } } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 1cb79e707..730992b13 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -325,7 +325,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return hasMessages(MSG_UPDATE_SUGGESTIONS); } - public void postUpdateShiftKeyState() { + public void postUpdateShiftState() { removeMessages(MSG_UPDATE_SHIFT_STATE); sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE), mDelayUpdateShiftState); } @@ -898,9 +898,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar resetComposingState(true /* alsoResetLastComposedWord */); updateSuggestions(); } + + mHandler.postUpdateShiftState(); } mExpectingUpdateSelection = false; - mHandler.postUpdateShiftKeyState(); // TODO: Decide to call restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() or not // here. It would probably be too expensive to call directly here but we may want to post a // message to delay it. The point would be to unify behavior between backspace to the @@ -1391,7 +1392,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mVoiceProxy.handleBackspace(); // In many cases, we may have to put the keyboard in auto-shift state again. - mHandler.postUpdateShiftKeyState(); + mHandler.postUpdateShiftState(); if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { // Cancel multi-character input: remove the text we just entered. diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index d32310096..dfcb6450e 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -65,7 +65,6 @@ public class Settings extends InputMethodSettingsActivity public static final String PREF_VIBRATE_ON = "vibrate_on"; public static final String PREF_SOUND_ON = "sound_on"; public static final String PREF_POPUP_ON = "popup_on"; - public static final String PREF_SHOW_SETTINGS_KEY = "show_settings_key"; public static final String PREF_VOICE_MODE = "voice_mode"; public static final String PREF_CORRECTION_SETTINGS = "correction_settings"; public static final String PREF_CONFIGURE_DICTIONARIES_KEY = "configure_dictionaries_key"; @@ -96,7 +95,6 @@ public class Settings extends InputMethodSettingsActivity private PreferenceScreen mKeypressVibrationDurationSettingsPref; private PreferenceScreen mKeypressSoundVolumeSettingsPref; private ListPreference mVoicePreference; - private CheckBoxPreference mShowSettingsKeyPreference; private ListPreference mShowCorrectionSuggestionsPreference; private ListPreference mAutoCorrectionThresholdPreference; private ListPreference mKeyPreviewPopupDismissDelay; @@ -147,7 +145,6 @@ public class Settings extends InputMethodSettingsActivity mInputLanguageSelection = (PreferenceScreen) findPreference(PREF_SUBTYPES_SETTINGS); mInputLanguageSelection.setOnPreferenceClickListener(this); mVoicePreference = (ListPreference) findPreference(PREF_VOICE_MODE); - mShowSettingsKeyPreference = (CheckBoxPreference) findPreference(PREF_SHOW_SETTINGS_KEY); mShowCorrectionSuggestionsPreference = (ListPreference) findPreference(PREF_SHOW_SUGGESTIONS_SETTING); SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); @@ -178,10 +175,6 @@ public class Settings extends InputMethodSettingsActivity final PreferenceGroup miscSettings = (PreferenceGroup) findPreference(PREF_MISC_SETTINGS); - if (!SettingsValues.isShowSettingsKeyOptionEnabled(res)) { - generalSettings.removePreference(mShowSettingsKeyPreference); - } - final boolean showVoiceKeyOption = res.getBoolean( R.bool.config_enable_show_voice_key_option); if (!showVoiceKeyOption) { diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index 6b652313c..7a43cb827 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -49,7 +49,6 @@ public class SettingsValues { public final boolean mVibrateOn; public final boolean mSoundOn; public final boolean mKeyPreviewPopupOn; - private final boolean mShowSettingsKey; private final String mVoiceMode; private final String mAutoCorrectionThresholdRawValue; public final String mShowSuggestionsSetting; @@ -118,7 +117,6 @@ public class SettingsValues { mSoundOn = prefs.getBoolean(Settings.PREF_SOUND_ON, res.getBoolean(R.bool.config_default_sound_enabled)); mKeyPreviewPopupOn = isKeyPreviewPopupEnabled(prefs, res); - mShowSettingsKey = isSettingsKeyShown(prefs, res); final String voiceModeMain = res.getString(R.string.voice_mode_main); final String voiceModeOff = res.getString(R.string.voice_mode_off); mVoiceMode = prefs.getString(Settings.PREF_VOICE_MODE, voiceModeMain); @@ -202,19 +200,6 @@ public class SettingsValues { return wordSeparators; } - private static boolean isSettingsKeyShown(final SharedPreferences prefs, final Resources res) { - final boolean defaultShowSettingsKey = res.getBoolean( - R.bool.config_default_show_settings_key); - return isShowSettingsKeyOptionEnabled(res) - ? prefs.getBoolean(Settings.PREF_SHOW_SETTINGS_KEY, defaultShowSettingsKey) - : defaultShowSettingsKey; - } - - public static boolean isShowSettingsKeyOptionEnabled(final Resources resources) { - // TODO: Read this once and for all into a public final member - return resources.getBoolean(R.bool.config_enable_show_settings_key_option); - } - private static boolean isVibrateOn(final Context context, final SharedPreferences prefs, final Resources res) { final boolean hasVibrator = VibratorCompatWrapper.getInstance(context).hasVibrator(); @@ -306,10 +291,6 @@ public class SettingsValues { return autoCorrectionThreshold; } - public boolean isSettingsKeyEnabled() { - return mShowSettingsKey; - } - public boolean isVoiceKeyEnabled(final EditorInfo editorInfo) { final boolean shortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled(); final int inputType = (editorInfo != null) ? editorInfo.inputType : 0; |