diff options
Diffstat (limited to 'java/src')
8 files changed, 243 insertions, 186 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index 5816e5680..c548f1145 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -680,7 +680,7 @@ public class Keyboard { a.recycle(); if (resourceId == 0) { if (LatinImeLogger.sDBG) - throw new RuntimeException("touchPositionCorrectionData is not defined"); + Log.e(TAG, "touchPositionCorrectionData is not defined"); return; } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java index d95c3b3af..edce4c6e8 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java @@ -39,16 +39,14 @@ public class KeyboardId { public static final int MODE_NUMBER = 5; 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_ALPHABET_MANUAL_SHIFTED = 1; + public static final int ELEMENT_ALPHABET_AUTOMATIC_SHIFTED = 2; + public static final int ELEMENT_ALPHABET_SHIFT_LOCKED = 3; + public static final int ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED = 4; public static final int ELEMENT_SYMBOLS = 5; - public static final int ELEMENT_SYMBOLS_SHIFT = 6; + public static final int ELEMENT_SYMBOLS_SHIFTED = 6; public static final int ELEMENT_PHONE = 7; - public static final int ELEMENT_PHONE_SHIFT = 8; + public static final int ELEMENT_PHONE_SHIFTED = 8; public static final int ELEMENT_NUMBER = 9; private static final int F2KEY_MODE_NONE = 0; @@ -60,7 +58,7 @@ public class KeyboardId { public final int mOrientation; public final int mWidth; public final int mMode; - public final int mElementState; + public final int mElement; private final int mInputType; private final int mImeOptions; private final boolean mSettingsKeyEnabled; @@ -70,14 +68,14 @@ public class KeyboardId { private final int mHashCode; - public KeyboardId(int elementState, Locale locale, int orientation, int width, int mode, + public KeyboardId(int element, 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.mElementState = elementState; + this.mElement = element; this.mInputType = inputType; this.mImeOptions = imeOptions; this.mSettingsKeyEnabled = settingsKeyEnabled; @@ -91,7 +89,7 @@ public class KeyboardId { private static int hashCode(KeyboardId id) { return Arrays.hashCode(new Object[] { id.mOrientation, - id.mElementState, + id.mElement, id.mMode, id.mWidth, id.navigateAction(), @@ -109,7 +107,7 @@ public class KeyboardId { if (other == this) return true; return other.mOrientation == this.mOrientation - && other.mElementState == this.mElementState + && other.mElement == this.mElement && other.mMode == this.mMode && other.mWidth == this.mWidth && other.navigateAction() == this.navigateAction() @@ -123,19 +121,19 @@ public class KeyboardId { } public boolean isAlphabetKeyboard() { - return mElementState < ELEMENT_SYMBOLS; + return mElement < ELEMENT_SYMBOLS; } public boolean isSymbolsKeyboard() { - return mElementState == ELEMENT_SYMBOLS || mElementState == ELEMENT_SYMBOLS_SHIFT; + return mElement == ELEMENT_SYMBOLS || mElement == ELEMENT_SYMBOLS_SHIFTED; } public boolean isPhoneKeyboard() { - return mElementState == ELEMENT_PHONE || mElementState == ELEMENT_PHONE_SHIFT; + return mElement == ELEMENT_PHONE || mElement == ELEMENT_PHONE_SHIFTED; } public boolean isPhoneShiftKeyboard() { - return mElementState == ELEMENT_PHONE_SHIFT; + return mElement == ELEMENT_PHONE_SHIFTED; } public boolean navigateAction() { @@ -190,7 +188,7 @@ public class KeyboardId { @Override public String toString() { return String.format("[%s %s %s%d %s %s %s%s%s%s%s%s%s]", - elementStateToString(mElementState), + elementToString(mElement), mLocale, (mOrientation == 1 ? "port" : "land"), mWidth, modeName(mMode), @@ -213,19 +211,17 @@ public class KeyboardId { && TextUtils.equals(a.privateImeOptions, b.privateImeOptions); } - public static String elementStateToString(int elementState) { - switch (elementState) { + public static String elementToString(int element) { + switch (element) { 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_ALPHABET_MANUAL_SHIFTED: return "alphabetManualShifted"; + case ELEMENT_ALPHABET_AUTOMATIC_SHIFTED: return "alphabetAutomaticShifted"; + case ELEMENT_ALPHABET_SHIFT_LOCKED: return "alphabetShiftLocked"; + case ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED: return "alphabetShiftLockShifted"; case ELEMENT_SYMBOLS: return "symbols"; - case ELEMENT_SYMBOLS_SHIFT: return "symbolsShift"; + case ELEMENT_SYMBOLS_SHIFTED: return "symbolsShifted"; case ELEMENT_PHONE: return "phone"; - case ELEMENT_PHONE_SHIFT: return "phoneShift"; + case ELEMENT_PHONE_SHIFTED: return "phoneShifted"; case ELEMENT_NUMBER: return "number"; default: return null; } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java index 285252044..f4602b8fd 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java @@ -22,6 +22,7 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.util.Log; +import android.util.TypedValue; import android.util.Xml; import android.view.inputmethod.EditorInfo; @@ -54,10 +55,12 @@ public class KeyboardSet { private static final String TAG_KEYBOARD_SET = TAG; private static final String TAG_ELEMENT = "Element"; + private static final int ELEMENT_KEYBOARD_AUTO_GENERATE_FROM_ALPHABET = 1; + private final Context mContext; private final Params mParams; - private static class Params { + static class Params { int mMode; int mInputType; int mImeOptions; @@ -104,16 +107,18 @@ public class KeyboardSet { } private Keyboard 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 int element = KeyboardSet.getElement(mParams.mMode, isSymbols, isShift); + // TODO: If xmlId is ELEMENT_KEYBOARD_AUTO_GENERATE_FROM_ALPHABET, auto generate the + // keyboard based on base main alphabet keyboard considering element. + final int xmlId = mParams.mElementKeyboards.get(element); + final KeyboardId id = KeyboardSet.getKeyboardId(element, isSymbols, mParams); final Keyboard 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); + final int element = KeyboardSet.getElement(mParams.mMode, false, false); + return KeyboardSet.getKeyboardId(element, false, mParams); } private Keyboard getKeyboard(Context context, int xmlId, KeyboardId id) { @@ -147,6 +152,30 @@ public class KeyboardSet { return keyboard; } + private static int getElement(int mode, boolean isSymbols, boolean isShift) { + switch (mode) { + case KeyboardId.MODE_PHONE: + return (isSymbols && isShift) + ? KeyboardId.ELEMENT_PHONE_SHIFTED : KeyboardId.ELEMENT_PHONE; + case KeyboardId.MODE_NUMBER: + return KeyboardId.ELEMENT_NUMBER; + default: + if (isSymbols) { + return isShift + ? KeyboardId.ELEMENT_SYMBOLS_SHIFTED : KeyboardId.ELEMENT_SYMBOLS; + } + return KeyboardId.ELEMENT_ALPHABET; + } + } + + private static KeyboardId getKeyboardId(int element, boolean isSymbols, Params params) { + final boolean hasShortcutKey = params.mVoiceKeyEnabled + && (isSymbols != params.mVoiceKeyOnMain); + return new KeyboardId(element, params.mLocale, params.mOrientation, params.mWidth, + params.mMode, params.mInputType, params.mImeOptions, params.mSettingsKeyEnabled, + params.mNoSettingsKey, params.mVoiceKeyEnabled, hasShortcutKey); + } + public static class Builder { private final Context mContext; private final String mPackageName; @@ -218,31 +247,6 @@ public class KeyboardSet { return new KeyboardSet(mContext, mParams); } - // 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); - } - - // TODO: Move this method to KeyboardSet - static int getElementState(int mode, boolean isSymbols, boolean isShift) { - switch (mode) { - case KeyboardId.MODE_PHONE: - return (isSymbols && isShift) - ? KeyboardId.ELEMENT_PHONE_SHIFT : KeyboardId.ELEMENT_PHONE; - case KeyboardId.MODE_NUMBER: - return KeyboardId.ELEMENT_NUMBER; - default: - if (isSymbols) { - 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); @@ -300,8 +304,14 @@ public class KeyboardSet { final int elementName = a.getInt( R.styleable.KeyboardSet_Element_elementName, 0); - final int elementKeyboard = a.getResourceId( - R.styleable.KeyboardSet_Element_elementKeyboard, 0); + final int index = R.styleable.KeyboardSet_Element_elementKeyboard; + final TypedValue v = a.peekValue(index); + final int elementKeyboard; + if (v.type == TypedValue.TYPE_REFERENCE) { + elementKeyboard = a.getResourceId(index, 0); + } else { + elementKeyboard = a.getInt(index, 0); + } mParams.mElementKeyboards.put(elementName, elementKeyboard); } finally { a.recycle(); diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index cb80d052e..1398bae2a 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -216,37 +216,53 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, return null; } - // Implements {@link KeyboardState.SwitchActions}. - @Override - public void setShifted(int shiftMode) { + /** + * Update keyboard shift state triggered by connected EditText status change. + */ + public void updateShiftState() { + mState.onUpdateShiftState(mInputMethodService.getCurrentAutoCapsState()); + } + + public void onPressKey(int code) { + mState.onPressKey(code); + } + + public void onReleaseKey(int code, boolean withSliding) { + mState.onReleaseKey(code, withSliding); + } + + public void onCancelInput() { + mState.onCancelInput(isSinglePointer()); + } + + // TODO: Remove these constants. + private static final int ALPHABET_UNSHIFTED = 0; + private static final int ALPHABET_MANUAL_SHIFTED = 1; + private static final int ALPHABET_AUTOMATIC_SHIFTED = 2; + private static final int ALPHABET_SHIFT_LOCKED = 3; + + // TODO: Remove this method. + private void updateAlphabetKeyboardShiftState(int shiftMode) { mInputMethodService.mHandler.cancelUpdateShiftState(); Keyboard keyboard = getKeyboard(); if (keyboard == null) return; switch (shiftMode) { - case AUTOMATIC_SHIFT: - keyboard.setAutomaticTemporaryUpperCase(); + case ALPHABET_UNSHIFTED: + keyboard.setShifted(false); break; - case MANUAL_SHIFT: + case ALPHABET_MANUAL_SHIFTED: keyboard.setShifted(true); break; - case UNSHIFT: - keyboard.setShifted(false); + case ALPHABET_AUTOMATIC_SHIFTED: + keyboard.setAutomaticTemporaryUpperCase(); + break; + case ALPHABET_SHIFT_LOCKED: + keyboard.setShiftLocked(true); break; } mKeyboardView.invalidateAllKeys(); - } - - // Implements {@link KeyboardState.SwitchActions}. - @Override - public void setShiftLocked(boolean shiftLocked) { - mInputMethodService.mHandler.cancelUpdateShiftState(); - Keyboard keyboard = getKeyboard(); - if (keyboard == null) - return; - keyboard.setShiftLocked(shiftLocked); - mKeyboardView.invalidateAllKeys(); - if (!shiftLocked) { + if (shiftMode != ALPHABET_SHIFT_LOCKED) { // To be able to turn off caps lock by "double tap" on shift key, we should ignore // the second tap of the "double tap" from now for a while because we just have // already turned off caps lock above. @@ -254,35 +270,38 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, } } - /** - * Update keyboard shift state triggered by connected EditText status change. - */ - public void updateShiftState() { - mState.onUpdateShiftState(mInputMethodService.getCurrentAutoCapsState()); - } - - public void onPressKey(int code) { - mState.onPressKey(code); + // Implements {@link KeyboardState.SwitchActions}. + @Override + public void setAlphabetKeyboard() { + setKeyboard(mKeyboardSet.getMainKeyboard()); + updateAlphabetKeyboardShiftState(ALPHABET_UNSHIFTED); } - public void onReleaseKey(int code, boolean withSliding) { - mState.onReleaseKey(code, withSliding); + // Implements {@link KeyboardState.SwitchActions}. + @Override + public void setAlphabetManualShiftedKeyboard() { + setKeyboard(mKeyboardSet.getMainKeyboard()); + updateAlphabetKeyboardShiftState(ALPHABET_MANUAL_SHIFTED); } - public void onCancelInput() { - mState.onCancelInput(isSinglePointer()); + // Implements {@link KeyboardState.SwitchActions}. + @Override + public void setAlphabetAutomaticShiftedKeyboard() { + setKeyboard(mKeyboardSet.getMainKeyboard()); + updateAlphabetKeyboardShiftState(ALPHABET_AUTOMATIC_SHIFTED); } // Implements {@link KeyboardState.SwitchActions}. @Override - public void setSymbolsKeyboard() { - setKeyboard(mKeyboardSet.getSymbolsKeyboard()); + public void setAlphabetShiftLockedKeyboard() { + setKeyboard(mKeyboardSet.getMainKeyboard()); + updateAlphabetKeyboardShiftState(ALPHABET_SHIFT_LOCKED); } // Implements {@link KeyboardState.SwitchActions}. @Override - public void setAlphabetKeyboard() { - setKeyboard(mKeyboardSet.getMainKeyboard()); + public void setSymbolsKeyboard() { + setKeyboard(mKeyboardSet.getSymbolsKeyboard()); } // Implements {@link KeyboardState.SwitchActions}. diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java index babf600a6..38c31adce 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -40,16 +40,12 @@ public class KeyboardState { public interface SwitchActions { public void setAlphabetKeyboard(); - - public static final int UNSHIFT = 0; - public static final int MANUAL_SHIFT = 1; - public static final int AUTOMATIC_SHIFT = 2; - public void setShifted(int shiftMode); - - public void setShiftLocked(boolean shiftLocked); - + public void setAlphabetManualShiftedKeyboard(); + public void setAlphabetAutomaticShiftedKeyboard(); + public void setAlphabetShiftLockedKeyboard(); + // TODO: Add this. + //public void setAlphabetShiftLockShiftedKeyboard(); public void setSymbolsKeyboard(); - public void setSymbolsShiftedKeyboard(); /** @@ -63,14 +59,14 @@ public class KeyboardState { private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift"); private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol"); + // TODO: Merge {@link #mSwitchState}, {@link #mIsAlphabetMode}, {@link #mAlphabetShiftState}, + // {@link #mIsSymbolShifted}, {@link #mPrevMainKeyboardWasShiftLocked}, and + // {@link #mPrevSymbolsKeyboardWasShifted} into single state variable. private static final int SWITCH_STATE_ALPHA = 0; private static final int SWITCH_STATE_SYMBOL_BEGIN = 1; private static final int SWITCH_STATE_SYMBOL = 2; - // The following states are used only on the distinct multi-touch panel devices. private static final int SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL = 3; private static final int SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE = 4; - private static final int SWITCH_STATE_CHORDING_ALPHA = 5; - private static final int SWITCH_STATE_CHORDING_SYMBOL = 6; private int mSwitchState = SWITCH_STATE_ALPHA; private String mLayoutSwitchBackSymbols; @@ -88,6 +84,7 @@ public class KeyboardState { public boolean mIsShiftLocked; public boolean mIsShifted; + @Override public String toString() { if (!mIsValid) return "INVALID"; if (mIsAlphabetMode) { @@ -155,7 +152,7 @@ public class KeyboardState { if (state.mIsAlphabetMode) { setShiftLocked(state.mIsShiftLocked); if (!state.mIsShiftLocked) { - setShifted(state.mIsShifted ? SwitchActions.MANUAL_SHIFT : SwitchActions.UNSHIFT); + setShifted(state.mIsShifted ? MANUAL_SHIFT : UNSHIFT); } } } @@ -165,30 +162,58 @@ public class KeyboardState { return mAlphabetShiftState.isShiftLocked(); } + private static final int UNSHIFT = 0; + private static final int MANUAL_SHIFT = 1; + private static final int AUTOMATIC_SHIFT = 2; + private void setShifted(int shiftMode) { if (DEBUG_ACTION) { - Log.d(TAG, "setShifted: shiftMode=" + shiftModeToString(shiftMode)); + Log.d(TAG, "setShifted: shiftMode=" + shiftModeToString(shiftMode) + " " + this); + } + if (!mIsAlphabetMode) return; + final int prevShiftMode; + if (mAlphabetShiftState.isAutomaticTemporaryUpperCase()) { + prevShiftMode = AUTOMATIC_SHIFT; + } else if (mAlphabetShiftState.isManualTemporaryUpperCase()) { + prevShiftMode = MANUAL_SHIFT; + } else { + prevShiftMode = UNSHIFT; } switch (shiftMode) { - case SwitchActions.AUTOMATIC_SHIFT: + case AUTOMATIC_SHIFT: mAlphabetShiftState.setAutomaticTemporaryUpperCase(); + if (shiftMode != prevShiftMode) { + mSwitchActions.setAlphabetAutomaticShiftedKeyboard(); + } break; - case SwitchActions.MANUAL_SHIFT: + case MANUAL_SHIFT: mAlphabetShiftState.setShifted(true); + if (shiftMode != prevShiftMode) { + mSwitchActions.setAlphabetManualShiftedKeyboard(); + } break; - case SwitchActions.UNSHIFT: + case UNSHIFT: mAlphabetShiftState.setShifted(false); + if (shiftMode != prevShiftMode) { + mSwitchActions.setAlphabetKeyboard(); + } break; } - mSwitchActions.setShifted(shiftMode); } private void setShiftLocked(boolean shiftLocked) { if (DEBUG_ACTION) { - Log.d(TAG, "setShiftLocked: shiftLocked=" + shiftLocked); + Log.d(TAG, "setShiftLocked: shiftLocked=" + shiftLocked + " " + this); + } + if (!mIsAlphabetMode) return; + if (shiftLocked && (!mAlphabetShiftState.isShiftLocked() + || mAlphabetShiftState.isShiftLockShifted())) { + mSwitchActions.setAlphabetShiftLockedKeyboard(); + } + if (!shiftLocked && mAlphabetShiftState.isShiftLocked()) { + mSwitchActions.setAlphabetKeyboard(); } mAlphabetShiftState.setShiftLocked(shiftLocked); - mSwitchActions.setShiftLocked(shiftLocked); } private void toggleAlphabetAndSymbols() { @@ -276,8 +301,7 @@ public class KeyboardState { if (code == Keyboard.CODE_SHIFT) { onReleaseShift(withSliding); } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { - // TODO: Make use of withSliding instead of relying on mSwitchState. - onReleaseSymbol(); + onReleaseSymbol(withSliding); } } @@ -287,11 +311,16 @@ public class KeyboardState { mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL; } - private void onReleaseSymbol() { - // Switch back to the previous keyboard mode if the user chords the mode change key and - // another key, then releases the mode change key. - if (mSwitchState == SWITCH_STATE_CHORDING_ALPHA) { + private void onReleaseSymbol(boolean withSliding) { + if (mSymbolKeyState.isChording()) { + // Switch back to the previous keyboard mode if the user chords the mode change key and + // another key, then releases the mode change key. toggleAlphabetAndSymbols(); + } else if (!withSliding) { + // If the mode change key is being released without sliding, we should forget the + // previous symbols keyboard shift state and simply switch back to symbols layout + // (never symbols shifted) next time the mode gets changed to symbols layout. + mPrevSymbolsKeyboardWasShifted = false; } mSymbolKeyState.onRelease(); } @@ -300,24 +329,18 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + " " + this); } - onUpdateShiftStateInternal(autoCaps); + updateAlphabetShiftState(autoCaps); } - private void onUpdateShiftStateInternal(boolean autoCaps) { - if (mIsAlphabetMode) { - if (!mAlphabetShiftState.isShiftLocked() && !mShiftKeyState.isIgnoring()) { - if (mShiftKeyState.isReleasing() && autoCaps) { - // Only when shift key is releasing, automatic temporary upper case will be set. - setShifted(SwitchActions.AUTOMATIC_SHIFT); - } else { - setShifted(mShiftKeyState.isMomentary() - ? SwitchActions.MANUAL_SHIFT : SwitchActions.UNSHIFT); - } + private void updateAlphabetShiftState(boolean autoCaps) { + if (!mIsAlphabetMode) return; + if (!mAlphabetShiftState.isShiftLocked() && !mShiftKeyState.isIgnoring()) { + if (mShiftKeyState.isReleasing() && autoCaps) { + // Only when shift key is releasing, automatic temporary upper case will be set. + setShifted(AUTOMATIC_SHIFT); + } else { + setShifted(mShiftKeyState.isChording() ? MANUAL_SHIFT : UNSHIFT); } - } else { - // In symbol keyboard mode, we should clear shift key state because only alphabet - // keyboard has shift key. - mSymbolKeyState.onRelease(); } } @@ -326,12 +349,12 @@ public class KeyboardState { if (mAlphabetShiftState.isShiftLocked()) { // Shift key is pressed while caps lock state, we will treat this state as shifted // caps lock state and mark as if shift key pressed while normal state. - setShifted(SwitchActions.MANUAL_SHIFT); + setShifted(MANUAL_SHIFT); mShiftKeyState.onPress(); } else if (mAlphabetShiftState.isAutomaticTemporaryUpperCase()) { // Shift key is pressed while automatic temporary upper case, we have to move to // manual temporary upper case. - setShifted(SwitchActions.MANUAL_SHIFT); + setShifted(MANUAL_SHIFT); mShiftKeyState.onPress(); } else if (mAlphabetShiftState.isShiftedOrShiftLocked()) { // In manual upper case state, we just record shift key has been pressing while @@ -339,7 +362,7 @@ public class KeyboardState { mShiftKeyState.onPressOnShifted(); } else { // In base layout, chording or manual temporary upper case mode is started. - setShifted(SwitchActions.MANUAL_SHIFT); + setShifted(MANUAL_SHIFT); mShiftKeyState.onPress(); } } else { @@ -353,13 +376,17 @@ public class KeyboardState { private void onReleaseShift(boolean withSliding) { if (mIsAlphabetMode) { final boolean isShiftLocked = mAlphabetShiftState.isShiftLocked(); - if (mShiftKeyState.isMomentary()) { - // After chording input while normal state. + if (mShiftKeyState.isChording()) { if (mAlphabetShiftState.isShiftLockShifted()) { + // After chording input while caps lock state. setShiftLocked(true); } else { - setShifted(SwitchActions.UNSHIFT); + // After chording input while normal state. + setShifted(UNSHIFT); } + } else if (mAlphabetShiftState.isShiftLockShifted() && withSliding) { + // In caps lock state, shift has been pressed and slid out to other key. + setShiftLocked(true); } else if (isShiftLocked && !mAlphabetShiftState.isShiftLockShifted() && (mShiftKeyState.isPressing() || mShiftKeyState.isPressingOnShifted()) && !withSliding) { @@ -370,17 +397,17 @@ public class KeyboardState { } else if (mAlphabetShiftState.isShiftedOrShiftLocked() && mShiftKeyState.isPressingOnShifted() && !withSliding) { // Shift has been pressed without chording while shifted state. - setShifted(SwitchActions.UNSHIFT); + setShifted(UNSHIFT); } else if (mAlphabetShiftState.isManualTemporaryUpperCaseFromAuto() && mShiftKeyState.isPressing() && !withSliding) { // Shift has been pressed without chording while manual temporary upper case // transited from automatic temporary upper case. - setShifted(SwitchActions.UNSHIFT); + setShifted(UNSHIFT); } } else { // In symbol mode, switch back to the previous keyboard mode if the user chords the // shift key and another key, then releases the shift key. - if (mSwitchState == SWITCH_STATE_CHORDING_SYMBOL) { + if (mShiftKeyState.isChording()) { toggleShiftInSymbols(); } } @@ -436,12 +463,6 @@ public class KeyboardState { switch (mSwitchState) { case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: - // Only distinct multi touch devices can be in this state. - // On non-distinct multi touch devices, mode change key is handled by - // {@link LatinIME#onCodeInput}, not by {@link LatinIME#onPress} and - // {@link LatinIME#onRelease}. So, on such devices, {@link #mSwitchState} starts - // from {@link #SWITCH_STATE_SYMBOL_BEGIN}, or {@link #SWITCH_STATE_ALPHA}, not from - // {@link #SWITCH_STATE_MOMENTARY}. if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { // Detected only the mode change key has been pressed, and then released. if (mIsAlphabetMode) { @@ -455,10 +476,6 @@ public class KeyboardState { // If the user cancels the sliding input, switching back to the previous keyboard // mode is handled by {@link #onCancelInput}. toggleAlphabetAndSymbols(); - } else { - // Chording input is being started. The keyboard mode will be switched back to the - // previous mode in {@link onReleaseSymbol} when the mode change key is released. - mSwitchState = SWITCH_STATE_CHORDING_ALPHA; } break; case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE: @@ -470,10 +487,6 @@ public class KeyboardState { // symbol mode and slid to other key, then released the finger. toggleShiftInSymbols(); mSwitchState = SWITCH_STATE_SYMBOL; - } else { - // Chording input is being started. The keyboard mode will be switched back to the - // previous mode in {@link onReleaseShift} when the shift key is released. - mSwitchState = SWITCH_STATE_CHORDING_SYMBOL; } break; case SWITCH_STATE_SYMBOL_BEGIN: @@ -487,7 +500,6 @@ public class KeyboardState { } break; case SWITCH_STATE_SYMBOL: - case SWITCH_STATE_CHORDING_SYMBOL: // Switch back to alpha keyboard mode if user types one or more non-space/enter // characters followed by a space/enter or a quote character. if (isSpaceCharacter(code) || isLayoutSwitchBackCharacter(code)) { @@ -498,15 +510,15 @@ public class KeyboardState { // If the code is a letter, update keyboard shift state. if (Keyboard.isLetterCode(code)) { - onUpdateShiftStateInternal(autoCaps); + updateAlphabetShiftState(autoCaps); } } private static String shiftModeToString(int shiftMode) { switch (shiftMode) { - case SwitchActions.UNSHIFT: return "UNSHIFT"; - case SwitchActions.MANUAL_SHIFT: return "MANUAL"; - case SwitchActions.AUTOMATIC_SHIFT: return "AUTOMATIC"; + case UNSHIFT: return "UNSHIFT"; + case MANUAL_SHIFT: return "MANUAL"; + case AUTOMATIC_SHIFT: return "AUTOMATIC"; default: return null; } } @@ -518,8 +530,6 @@ public class KeyboardState { case SWITCH_STATE_SYMBOL: return "SYMBOL"; case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: return "MOMENTARY-ALPHA-SYMBOL"; case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE: return "MOMENTARY-SYMBOL-MORE"; - case SWITCH_STATE_CHORDING_ALPHA: return "CHORDING-ALPHA"; - case SWITCH_STATE_CHORDING_SYMBOL: return "CHORDING-SYMBOL"; default: return null; } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java b/java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java index f95c91636..b39b97720 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java @@ -19,12 +19,12 @@ package com.android.inputmethod.keyboard.internal; import android.util.Log; /* package */ class ModifierKeyState { - protected static final String TAG = "ModifierKeyState"; + protected static final String TAG = ModifierKeyState.class.getSimpleName(); protected static final boolean DEBUG = false; protected static final int RELEASING = 0; protected static final int PRESSING = 1; - protected static final int MOMENTARY = 2; + protected static final int CHORDING = 2; protected final String mName; protected int mState = RELEASING; @@ -50,7 +50,7 @@ import android.util.Log; public void onOtherKeyPressed() { final int oldState = mState; if (oldState == PRESSING) - mState = MOMENTARY; + mState = CHORDING; if (DEBUG) Log.d(TAG, mName + ".onOtherKeyPressed: " + toString(oldState) + " > " + this); } @@ -63,8 +63,8 @@ import android.util.Log; return mState == RELEASING; } - public boolean isMomentary() { - return mState == MOMENTARY; + public boolean isChording() { + return mState == CHORDING; } @Override @@ -76,7 +76,7 @@ import android.util.Log; switch (state) { case RELEASING: return "RELEASING"; case PRESSING: return "PRESSING"; - case MOMENTARY: return "MOMENTARY"; + case CHORDING: return "CHORDING"; default: return "UNKNOWN"; } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java b/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java index 6f54b4f23..edb40c8e7 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java @@ -30,7 +30,7 @@ import android.util.Log; public void onOtherKeyPressed() { int oldState = mState; if (oldState == PRESSING) { - mState = MOMENTARY; + mState = CHORDING; } else if (oldState == PRESSING_ON_SHIFTED) { mState = IGNORING; } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 94c47bdc9..31cbc4ee3 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -203,9 +203,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private WordComposer mWordComposer = new WordComposer(); private int mCorrectionMode; + // Keep track of the last selection range to decide if we need to show word alternatives - private int mLastSelectionStart; - private int mLastSelectionEnd; + private static final int NOT_A_CURSOR_POSITION = -1; + private int mLastSelectionStart = NOT_A_CURSOR_POSITION; + private int mLastSelectionEnd = NOT_A_CURSOR_POSITION; // Whether we are expecting an onUpdateSelection event to fire. If it does when we don't // "expect" it, it means the user actually moved the cursor. @@ -391,7 +393,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Working variables for the following methods. private boolean mIsOrientationChanging; - private boolean mPendingSuccesiveImsCallback; + private boolean mPendingSuccessiveImsCallback; private boolean mHasPendingStartInput; private boolean mHasPendingFinishInputView; private boolean mHasPendingFinishInput; @@ -432,7 +434,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (mIsOrientationChanging && restarting) { // This is the first onStartInput after orientation changed. mIsOrientationChanging = false; - mPendingSuccesiveImsCallback = true; + mPendingSuccessiveImsCallback = true; } final LatinIME latinIme = getOuterInstance(); executePendingImsCallback(latinIme, editorInfo, restarting); @@ -446,9 +448,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Typically this is the second onStartInputView after orientation changed. resetPendingImsCallback(); } else { - if (mPendingSuccesiveImsCallback) { + if (mPendingSuccessiveImsCallback) { // This is the first onStartInputView after orientation changed. - mPendingSuccesiveImsCallback = false; + mPendingSuccessiveImsCallback = false; resetPendingImsCallback(); sendMessageDelayed(obtainMessage(MSG_PENDING_IMS_CALLBACK), PENDING_IMS_CALLBACK_DURATION); @@ -1401,9 +1403,29 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // inconsistent with backspacing after selecting other suggestions. restartSuggestionsOnManuallyPickedTypedWord(ic); } else { - ic.deleteSurroundingText(1, 0); - if (mDeleteCount > DELETE_ACCELERATE_AT) { - ic.deleteSurroundingText(1, 0); + // Here we must check whether there is a selection. If so we should remove the + // selected text, otherwise we should just delete the character before the cursor. + if (mLastSelectionStart != mLastSelectionEnd) { + final int lengthToDelete = mLastSelectionEnd - mLastSelectionStart; + ic.setSelection(mLastSelectionEnd, mLastSelectionEnd); + ic.deleteSurroundingText(lengthToDelete, 0); + } else { + if (NOT_A_CURSOR_POSITION == mLastSelectionEnd) { + // We don't know whether there is a selection or not. We just send a false + // hardware key event and let TextView sort it out for us. The problem + // here is, this is asynchronous with respect to the input connection + // batch edit, so it may flicker. But this only ever happens if backspace + // is pressed just after the IME is invoked, and then again only once. + // TODO: add an API call that gets the selection indices. This is available + // to the IME in the general case via onUpdateSelection anyway, and would + // allow us to remove this race condition. + sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); + } else { + ic.deleteSurroundingText(1, 0); + } + if (mDeleteCount > DELETE_ACCELERATE_AT) { + ic.deleteSurroundingText(1, 0); + } } if (isSuggestionsRequested()) { restartSuggestionsOnWordBeforeCursorIfAtEndOfWord(ic); |