diff options
Diffstat (limited to 'java/src')
12 files changed, 151 insertions, 116 deletions
diff --git a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java index 89e623a1d..bef4d8594 100644 --- a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java +++ b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java @@ -52,12 +52,16 @@ public class DeadKeyCombiner implements Combiner { // how dead keys work). // If the event is a space, we should commit the dead char alone, but if it's // not, we need to commit both. + // TODO: this is not necessarily triggered by hardware key events, so it's not + // a good idea to masquerade as one. This should be typed as a software + // composite event or something. return Event.createHardwareKeypressEvent(deadCodePoint, event.mKeyCode, - Constants.CODE_SPACE == event.mCodePoint ? null : event /* next */); + Constants.CODE_SPACE == event.mCodePoint ? null : event /* next */, + false /* isKeyRepeat */); } else { // We could combine the characters. return Event.createHardwareKeypressEvent(resultingCodePoint, event.mKeyCode, - null /* next */); + null /* next */, false /* isKeyRepeat */); } } } diff --git a/java/src/com/android/inputmethod/event/Event.java b/java/src/com/android/inputmethod/event/Event.java index 6535d2d76..4a9163c8e 100644 --- a/java/src/com/android/inputmethod/event/Event.java +++ b/java/src/com/android/inputmethod/event/Event.java @@ -65,6 +65,8 @@ public class Event { // This event is a dead character, usually input by a dead key. Examples include dead-acute // or dead-abovering. final private static int FLAG_DEAD = 0x1; + // This event is coming from a key repeat, software or hardware. + final private static int FLAG_REPEAT = 0x2; final private int mEventType; // The type of event - one of the constants above // The code point associated with the event, if relevant. This is a unicode code point, and @@ -130,16 +132,16 @@ public class Event { } public static Event createSoftwareKeypressEvent(final int codePoint, final int keyCode, - final int x, final int y) { + final int x, final int y, final boolean isKeyRepeat) { return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode, x, y, - null /* suggestedWordInfo */, FLAG_NONE, null /* next */); + null /* suggestedWordInfo */, isKeyRepeat ? FLAG_REPEAT : FLAG_NONE, null); } public static Event createHardwareKeypressEvent(final int codePoint, final int keyCode, - final Event next) { + final Event next, final boolean isKeyRepeat) { return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode, Constants.EXTERNAL_KEYBOARD_COORDINATE, Constants.EXTERNAL_KEYBOARD_COORDINATE, - null /* suggestedWordInfo */, FLAG_NONE, next); + null /* suggestedWordInfo */, isKeyRepeat ? FLAG_REPEAT : FLAG_NONE, next); } // This creates an input event for a dead character. @see {@link #FLAG_DEAD} @@ -228,6 +230,10 @@ public class Event { return 0 != (FLAG_DEAD & mFlags); } + public boolean isKeyRepeat() { + return 0 != (FLAG_REPEAT & mFlags); + } + // Returns whether this is a fake key press from the suggestion strip. This happens with // punctuation signs selected from the suggestion strip. public boolean isSuggestionStripPress() { diff --git a/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java b/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java index da6780e08..05ba99923 100644 --- a/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java +++ b/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java @@ -46,9 +46,10 @@ public class HardwareKeyboardEventDecoder implements HardwareEventDecoder { // do not necessarily map to a unicode character. This represents a physical key, like // the key for 'A' or Space, but also Backspace or Ctrl or Caps Lock. final int keyCode = keyEvent.getKeyCode(); + final boolean isKeyRepeat = (0 != keyEvent.getRepeatCount()); if (KeyEvent.KEYCODE_DEL == keyCode) { return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT, Constants.CODE_DELETE, - null /* next */); + null /* next */, isKeyRepeat); } if (keyEvent.isPrintingKey() || KeyEvent.KEYCODE_SPACE == keyCode || KeyEvent.KEYCODE_ENTER == keyCode) { @@ -65,15 +66,16 @@ public class HardwareKeyboardEventDecoder implements HardwareEventDecoder { // Latin IME decide what to do with it. if (keyEvent.isShiftPressed()) { return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT, - Constants.CODE_SHIFT_ENTER, null /* next */); + Constants.CODE_SHIFT_ENTER, null /* next */, isKeyRepeat); } else { return Event.createHardwareKeypressEvent(Constants.CODE_ENTER, keyCode, - null /* next */); + null /* next */, isKeyRepeat); } } // If not Enter, then this is just a regular keypress event for a normal character // that can be committed right away, taking into account the current state. - return Event.createHardwareKeypressEvent(keyCode, codePointAndFlags, null /* next */); + return Event.createHardwareKeypressEvent(keyCode, codePointAndFlags, null /* next */, + isKeyRepeat); } return Event.createNotHandledEvent(); } diff --git a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java index 4edc61690..8822ccec9 100644 --- a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java +++ b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java @@ -606,7 +606,8 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange return; } final int code = (Integer) tag; - mKeyboardActionListener.onCodeInput(code, NOT_A_COORDINATE, NOT_A_COORDINATE); + mKeyboardActionListener.onCodeInput(code, NOT_A_COORDINATE, NOT_A_COORDINATE, + false /* isKeyRepeat */); mKeyboardActionListener.onReleaseKey(code, false /* withSliding */); } @@ -634,7 +635,8 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange if (code == Constants.CODE_OUTPUT_TEXT) { mKeyboardActionListener.onTextInput(key.getOutputText()); } else { - mKeyboardActionListener.onCodeInput(code, NOT_A_COORDINATE, NOT_A_COORDINATE); + mKeyboardActionListener.onCodeInput(code, NOT_A_COORDINATE, NOT_A_COORDINATE, + false /* isKeyRepeat */); } mKeyboardActionListener.onReleaseKey(code, false /* withSliding */); } @@ -901,8 +903,8 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange } private void handleKeyUp() { - mKeyboardActionListener.onCodeInput( - Constants.CODE_DELETE, NOT_A_COORDINATE, NOT_A_COORDINATE); + mKeyboardActionListener.onCodeInput(Constants.CODE_DELETE, + NOT_A_COORDINATE, NOT_A_COORDINATE, false /* isKeyRepeat */); mKeyboardActionListener.onReleaseKey( Constants.CODE_DELETE, false /* withSliding */); ++mRepeatCount; diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java index dc760e685..c565866b7 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java @@ -53,8 +53,10 @@ public interface KeyboardActionListener { * {@link PointerTracker} or so, the value should be * {@link Constants#NOT_A_COORDINATE}.If it's called on insertion from the * suggestion strip, it should be {@link Constants#SUGGESTION_STRIP_COORDINATE}. + * @param isKeyRepeat true if this is a key repeat, false otherwise */ - public void onCodeInput(int primaryCode, int x, int y); + // TODO: change this to send an Event object instead + public void onCodeInput(int primaryCode, int x, int y, boolean isKeyRepeat); /** * Sends a string of characters to the listener. @@ -107,7 +109,7 @@ public interface KeyboardActionListener { @Override public void onReleaseKey(int primaryCode, boolean withSliding) {} @Override - public void onCodeInput(int primaryCode, int x, int y) {} + public void onCodeInput(int primaryCode, int x, int y, boolean isKeyRepeat) {} @Override public void onTextInput(String text) {} @Override diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index 6131a9b17..dcf7f7472 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -111,7 +111,8 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { return false; } - public void loadKeyboard(final EditorInfo editorInfo, final SettingsValues settingsValues) { + public void loadKeyboard(final EditorInfo editorInfo, final SettingsValues settingsValues, + final int currentAutoCapsState, final int currentRecapitalizeState) { final KeyboardLayoutSet.Builder builder = new KeyboardLayoutSet.Builder( mThemeContext, editorInfo); final Resources res = mThemeContext.getResources(); @@ -126,7 +127,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { mKeyboardLayoutSet = builder.build(); mCurrentSettingsValues = settingsValues; try { - mState.onLoadKeyboard(); + mState.onLoadKeyboard(currentAutoCapsState, currentRecapitalizeState); mKeyboardTextsSet.setLocale(mSubtypeSwitcher.getCurrentSubtypeLocale(), mThemeContext); } catch (KeyboardLayoutSetException e) { Log.w(TAG, "loading keyboard failed: " + e.mKeyboardId, e.getCause()); @@ -185,21 +186,24 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { // TODO: Remove this method. Come up with a more comprehensive way to reset the keyboard layout // when a keyboard layout set doesn't get reloaded in LatinIME.onStartInputViewInternal(). - public void resetKeyboardStateToAlphabet() { - mState.onResetKeyboardStateToAlphabet(); + public void resetKeyboardStateToAlphabet(final int currentAutoCapsState, + final int currentRecapitalizeState) { + mState.onResetKeyboardStateToAlphabet(currentAutoCapsState, currentRecapitalizeState); } public void onPressKey(final int code, final boolean isSinglePointer, - final int currentAutoCapsState) { - mState.onPressKey(code, isSinglePointer, currentAutoCapsState); + final int currentAutoCapsState, final int currentRecapitalizeState) { + mState.onPressKey(code, isSinglePointer, currentAutoCapsState, currentRecapitalizeState); } - public void onReleaseKey(final int code, final boolean withSliding) { - mState.onReleaseKey(code, withSliding); + public void onReleaseKey(final int code, final boolean withSliding, + final int currentAutoCapsState, final int currentRecapitalizeState) { + mState.onReleaseKey(code, withSliding, currentAutoCapsState, currentRecapitalizeState); } - public void onFinishSlidingInput() { - mState.onFinishSlidingInput(); + public void onFinishSlidingInput(final int currentAutoCapsState, + final int currentRecapitalizeState) { + mState.onFinishSlidingInput(currentAutoCapsState, currentRecapitalizeState); } // Implements {@link KeyboardState.SwitchActions}. @@ -260,14 +264,6 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS_SHIFTED)); } - // Implements {@link KeyboardState.SwitchActions}. - // TODO[IL]: merge the two following methods; remove the one without args. - @Override - public void requestUpdatingShiftState() { - mState.onUpdateShiftState(mLatinIME.getCurrentAutoCapsState(), - mLatinIME.getCurrentRecapitalizeState()); - } - // Future method for requesting an updating to the shift state. public void requestUpdatingShiftState(final int currentAutoCapsState, final int currentRecapitalizeState) { @@ -302,8 +298,9 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { /** * Updates state machine to figure out when to automatically switch back to the previous mode. */ - public void onCodeInput(final int code, final int currentAutoCapsState) { - mState.onCodeInput(code, currentAutoCapsState); + public void onCodeInput(final int code, final int currentAutoCapsState, + final int currentRecapitalizeState) { + mState.onCodeInput(code, currentAutoCapsState, currentRecapitalizeState); } public boolean isShowingEmojiPalettes() { diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index d8dd93a35..1cafd4162 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -626,8 +626,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack final int moreKeyCode = key.getMoreKeys()[0].mCode; tracker.onLongPressed(); listener.onPressKey(moreKeyCode, 0 /* repeatCount */, true /* isSinglePointer */); - listener.onCodeInput(moreKeyCode, - Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); + listener.onCodeInput(moreKeyCode, Constants.NOT_A_COORDINATE, + Constants.NOT_A_COORDINATE, false /* isKeyRepeat */); listener.onReleaseKey(moreKeyCode, false /* withSliding */); return; } diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java index fc331970b..65242dd76 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java @@ -143,9 +143,10 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel mListener.onTextInput(mCurrentKey.getOutputText()); } else if (code != Constants.CODE_UNSPECIFIED) { if (getKeyboard().hasProximityCharsCorrection(code)) { - mListener.onCodeInput(code, x, y); + mListener.onCodeInput(code, x, y, false /* isKeyRepeat */); } else { - mListener.onCodeInput(code, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); + mListener.onCodeInput(code, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, + false /* isKeyRepeat */); } } } diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 3539a874c..4777166ea 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -325,7 +325,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element, // Note that we need primaryCode argument because the keyboard may in shifted state and the // primaryCode is different from {@link Key#mKeyCode}. private void callListenerOnCodeInput(final Key key, final int primaryCode, final int x, - final int y, final long eventTime) { + final int y, final long eventTime, final boolean isKeyRepeat) { final boolean ignoreModifierKey = mIsInDraggingFinger && key.isModifier(); final boolean altersCode = key.altCodeWhileTyping() && sTimerProxy.isTypingState(); final int code = altersCode ? key.getAltCode() : primaryCode; @@ -350,10 +350,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element, sListener.onTextInput(key.getOutputText()); } else if (code != Constants.CODE_UNSPECIFIED) { if (mKeyboard.hasProximityCharsCorrection(code)) { - sListener.onCodeInput(code, x, y); + sListener.onCodeInput(code, x, y, isKeyRepeat); } else { sListener.onCodeInput(code, - Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); + Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, isKeyRepeat); } } } @@ -1204,7 +1204,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element, } final int code = key.getCode(); - callListenerOnCodeInput(key, code, x, y, eventTime); + callListenerOnCodeInput(key, code, x, y, eventTime, false /* isKeyRepeat */); callListenerOnRelease(key, code, false /* withSliding */); } @@ -1229,7 +1229,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element, final int nextRepeatCount = repeatCount + 1; startKeyRepeatTimer(nextRepeatCount); callListenerOnPressAndCheckKeyboardLayoutChange(key, repeatCount); - callListenerOnCodeInput(key, code, mKeyX, mKeyY, SystemClock.uptimeMillis()); + callListenerOnCodeInput(key, code, mKeyX, mKeyY, SystemClock.uptimeMillis(), + true /* isKeyRepeat */); } private void startKeyRepeatTimer(final int repeatCount) { diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java index ec0b5c95f..b98ced97c 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -27,10 +27,10 @@ import com.android.inputmethod.latin.utils.RecapitalizeStatus; * * This class contains all keyboard state transition logic. * - * The input events are {@link #onLoadKeyboard()}, {@link #onSaveKeyboardState()}, - * {@link #onPressKey(int,boolean,int)}, {@link #onReleaseKey(int,boolean)}, - * {@link #onCodeInput(int,int)}, {@link #onFinishSlidingInput()}, - * {@link #onUpdateShiftState(int,int)}, {@link #onResetKeyboardStateToAlphabet()}. + * The input events are {@link #onLoadKeyboard(int, int)}, {@link #onSaveKeyboardState()}, + * {@link #onPressKey(int,boolean,int,int)}, {@link #onReleaseKey(int,boolean,int,int)}, + * {@link #onCodeInput(int,int,int)}, {@link #onFinishSlidingInput(int,int)}, + * {@link #onUpdateShiftState(int,int)}, {@link #onResetKeyboardStateToAlphabet(int,int)}. * * The actions are {@link SwitchActions}'s methods. */ @@ -52,7 +52,8 @@ public final class KeyboardState { /** * Request to call back {@link KeyboardState#onUpdateShiftState(int, int)}. */ - public void requestUpdatingShiftState(); + public void requestUpdatingShiftState(final int currentAutoCapsState, + final int currentRecapitalizeState); public void startDoubleTapShiftKeyTimer(); public boolean isInDoubleTapShiftKeyTimeout(); @@ -117,7 +118,8 @@ public final class KeyboardState { mRecapitalizeMode = RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE; } - public void onLoadKeyboard() { + public void onLoadKeyboard(final int currentAutoCapsState, + final int currentRecapitalizeState) { if (DEBUG_EVENT) { Log.d(TAG, "onLoadKeyboard: " + this); } @@ -127,7 +129,7 @@ public final class KeyboardState { mPrevSymbolsKeyboardWasShifted = false; mShiftKeyState.onRelease(); mSymbolKeyState.onRelease(); - onRestoreKeyboardState(); + onRestoreKeyboardState(currentAutoCapsState, currentRecapitalizeState); } private static final int UNSHIFT = 0; @@ -153,13 +155,14 @@ public final class KeyboardState { } } - private void onRestoreKeyboardState() { + private void onRestoreKeyboardState(final int currentAutoCapsState, + final int currentRecapitalizeState) { final SavedKeyboardState state = mSavedKeyboardState; if (DEBUG_EVENT) { Log.d(TAG, "onRestoreKeyboardState: saved=" + state + " " + this); } if (!state.mIsValid || state.mIsAlphabetMode) { - setAlphabetKeyboard(); + setAlphabetKeyboard(currentAutoCapsState, currentRecapitalizeState); } else if (state.mIsEmojiMode) { setEmojiKeyboard(); } else { @@ -237,7 +240,8 @@ public final class KeyboardState { mAlphabetShiftState.setShiftLocked(shiftLocked); } - private void toggleAlphabetAndSymbols() { + private void toggleAlphabetAndSymbols(final int currentAutoCapsState, + final int currentRecapitalizeState) { if (DEBUG_ACTION) { Log.d(TAG, "toggleAlphabetAndSymbols: " + this); } @@ -251,7 +255,7 @@ public final class KeyboardState { mPrevSymbolsKeyboardWasShifted = false; } else { mPrevSymbolsKeyboardWasShifted = mIsSymbolShifted; - setAlphabetKeyboard(); + setAlphabetKeyboard(currentAutoCapsState, currentRecapitalizeState); if (mPrevMainKeyboardWasShiftLocked) { setShiftLocked(true); } @@ -261,14 +265,15 @@ public final class KeyboardState { // TODO: Remove this method. Come up with a more comprehensive way to reset the keyboard layout // when a keyboard layout set doesn't get reloaded in LatinIME.onStartInputViewInternal(). - private void resetKeyboardStateToAlphabet() { + private void resetKeyboardStateToAlphabet(final int currentAutoCapsState, + final int currentRecapitalizeState) { if (DEBUG_ACTION) { Log.d(TAG, "resetKeyboardStateToAlphabet: " + this); } if (mIsAlphabetMode) return; mPrevSymbolsKeyboardWasShifted = mIsSymbolShifted; - setAlphabetKeyboard(); + setAlphabetKeyboard(currentAutoCapsState, currentRecapitalizeState); if (mPrevMainKeyboardWasShiftLocked) { setShiftLocked(true); } @@ -283,7 +288,8 @@ public final class KeyboardState { } } - private void setAlphabetKeyboard() { + private void setAlphabetKeyboard(final int currentAutoCapsState, + final int currentRecapitalizeState) { if (DEBUG_ACTION) { Log.d(TAG, "setAlphabetKeyboard"); } @@ -294,7 +300,7 @@ public final class KeyboardState { mIsSymbolShifted = false; mRecapitalizeMode = RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE; mSwitchState = SWITCH_STATE_ALPHA; - mSwitchActions.requestUpdatingShiftState(); + mSwitchActions.requestUpdatingShiftState(currentAutoCapsState, currentRecapitalizeState); } private void setSymbolsKeyboard() { @@ -336,10 +342,11 @@ public final class KeyboardState { mSwitchActions.setEmojiKeyboard(); } - public void onPressKey(final int code, final boolean isSinglePointer, final int autoCaps) { + public void onPressKey(final int code, final boolean isSinglePointer, + final int currentAutoCapsState, final int currentRecapitalizeState) { if (DEBUG_EVENT) { - Log.d(TAG, "onPressKey: code=" + Constants.printableCode(code) - + " single=" + isSinglePointer + " autoCaps=" + autoCaps + " " + this); + Log.d(TAG, "onPressKey: code=" + Constants.printableCode(code) + " single=" + + isSinglePointer + " autoCaps=" + currentAutoCapsState + " " + this); } if (code != Constants.CODE_SHIFT) { // Because the double tap shift key timer is to detect two consecutive shift key press, @@ -351,7 +358,7 @@ public final class KeyboardState { } else if (code == Constants.CODE_CAPSLOCK) { // Nothing to do here. See {@link #onReleaseKey(int,boolean)}. } else if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) { - onPressSymbol(); + onPressSymbol(currentAutoCapsState, currentRecapitalizeState); } else { mShiftKeyState.onOtherKeyPressed(); mSymbolKeyState.onOtherKeyPressed(); @@ -363,7 +370,8 @@ public final class KeyboardState { // As for #3, please note that it's required to check even when the auto caps mode is // off because, for example, we may be in the #1 state within the manual temporary // shifted mode. - if (!isSinglePointer && mIsAlphabetMode && autoCaps != TextUtils.CAP_MODE_CHARACTERS) { + if (!isSinglePointer && mIsAlphabetMode + && currentAutoCapsState != TextUtils.CAP_MODE_CHARACTERS) { final boolean needsToResetAutoCaps = mAlphabetShiftState.isAutomaticShifted() || (mAlphabetShiftState.isManualShifted() && mShiftKeyState.isReleasing()); if (needsToResetAutoCaps) { @@ -373,31 +381,34 @@ public final class KeyboardState { } } - public void onReleaseKey(final int code, final boolean withSliding) { + public void onReleaseKey(final int code, final boolean withSliding, + final int currentAutoCapsState, final int currentRecapitalizeState) { if (DEBUG_EVENT) { Log.d(TAG, "onReleaseKey: code=" + Constants.printableCode(code) + " sliding=" + withSliding + " " + this); } if (code == Constants.CODE_SHIFT) { - onReleaseShift(withSliding); + onReleaseShift(withSliding, currentAutoCapsState, currentRecapitalizeState); } else if (code == Constants.CODE_CAPSLOCK) { setShiftLocked(!mAlphabetShiftState.isShiftLocked()); } else if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) { - onReleaseSymbol(withSliding); + onReleaseSymbol(withSliding, currentAutoCapsState, currentRecapitalizeState); } } - private void onPressSymbol() { - toggleAlphabetAndSymbols(); + private void onPressSymbol(final int currentAutoCapsState, + final int currentRecapitalizeState) { + toggleAlphabetAndSymbols(currentAutoCapsState, currentRecapitalizeState); mSymbolKeyState.onPress(); mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL; } - private void onReleaseSymbol(final boolean withSliding) { + private void onReleaseSymbol(final boolean withSliding, final int currentAutoCapsState, + final int currentRecapitalizeState) { 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(); + toggleAlphabetAndSymbols(currentAutoCapsState, currentRecapitalizeState); } 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 @@ -418,11 +429,12 @@ public final class KeyboardState { // TODO: Remove this method. Come up with a more comprehensive way to reset the keyboard layout // when a keyboard layout set doesn't get reloaded in LatinIME.onStartInputViewInternal(). - public void onResetKeyboardStateToAlphabet() { + public void onResetKeyboardStateToAlphabet(final int currentAutoCapsState, + final int currentRecapitalizeState) { if (DEBUG_EVENT) { Log.d(TAG, "onResetKeyboardStateToAlphabet: " + this); } - resetKeyboardStateToAlphabet(); + resetKeyboardStateToAlphabet(currentAutoCapsState, currentRecapitalizeState); } private void updateShiftStateForRecapitalize(final int recapitalizeMode) { @@ -513,7 +525,8 @@ public final class KeyboardState { } } - private void onReleaseShift(final boolean withSliding) { + private void onReleaseShift(final boolean withSliding, final int currentAutoCapsState, + final int currentRecapitalizeState) { if (RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE != mRecapitalizeMode) { // We are recapitalizing. We should match the keyboard state to the recapitalize // state in priority. @@ -536,7 +549,8 @@ public final class KeyboardState { // After chording input, automatic shift state may have been changed depending on // what characters were input. mShiftKeyState.onRelease(); - mSwitchActions.requestUpdatingShiftState(); + mSwitchActions.requestUpdatingShiftState(currentAutoCapsState, + currentRecapitalizeState); return; } else if (mAlphabetShiftState.isShiftLockShifted() && withSliding) { // In shift locked state, shift has been pressed and slid out to other key. @@ -573,20 +587,21 @@ public final class KeyboardState { mShiftKeyState.onRelease(); } - public void onFinishSlidingInput() { + public void onFinishSlidingInput(final int currentAutoCapsState, + final int currentRecapitalizeState) { if (DEBUG_EVENT) { Log.d(TAG, "onFinishSlidingInput: " + this); } // Switch back to the previous keyboard mode if the user cancels sliding input. switch (mSwitchState) { case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: - toggleAlphabetAndSymbols(); + toggleAlphabetAndSymbols(currentAutoCapsState, currentRecapitalizeState); break; case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE: toggleShiftInSymbols(); break; case SWITCH_STATE_MOMENTARY_ALPHA_SHIFT: - setAlphabetKeyboard(); + setAlphabetKeyboard(currentAutoCapsState, currentRecapitalizeState); break; } } @@ -595,10 +610,11 @@ public final class KeyboardState { return c == Constants.CODE_SPACE || c == Constants.CODE_ENTER; } - public void onCodeInput(final int code, final int autoCaps) { + public void onCodeInput(final int code, final int currentAutoCapsState, + final int currentRecapitalizeState) { if (DEBUG_EVENT) { Log.d(TAG, "onCodeInput: code=" + Constants.printableCode(code) - + " autoCaps=" + autoCaps + " " + this); + + " autoCaps=" + currentAutoCapsState + " " + this); } switch (mSwitchState) { @@ -634,7 +650,7 @@ public final class KeyboardState { // Switch back to alpha keyboard mode if user types one or more non-space/enter // characters followed by a space/enter. if (isSpaceOrEnter(code)) { - toggleAlphabetAndSymbols(); + toggleAlphabetAndSymbols(currentAutoCapsState, currentRecapitalizeState); mPrevSymbolsKeyboardWasShifted = false; } break; @@ -642,11 +658,11 @@ public final class KeyboardState { // If the code is a letter, update keyboard shift state. if (Constants.isLetterCode(code)) { - updateAlphabetShiftState(autoCaps, RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE); + updateAlphabetShiftState(currentAutoCapsState, currentRecapitalizeState); } else if (code == Constants.CODE_EMOJI) { setEmojiKeyboard(); } else if (code == Constants.CODE_ALPHA_FROM_EMOJI) { - setAlphabetKeyboard(); + setAlphabetKeyboard(currentAutoCapsState, currentRecapitalizeState); } } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 84558ca24..1fdb8d16c 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -236,7 +236,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // If we were able to reset the caches, then we can reload the keyboard. // Otherwise, we'll do it when we can. latinIme.mKeyboardSwitcher.loadKeyboard(latinIme.getCurrentInputEditorInfo(), - settingsValues); + settingsValues, latinIme.getCurrentAutoCapsState(), + latinIme.getCurrentAutoCapsState()); } break; } @@ -833,7 +834,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen suggest.setAutoCorrectionThreshold(currentSettingsValues.mAutoCorrectionThreshold); } - switcher.loadKeyboard(editorInfo, currentSettingsValues); + switcher.loadKeyboard(editorInfo, currentSettingsValues, getCurrentAutoCapsState(), + getCurrentRecapitalizeState()); if (!canReachInputConnection) { // If we can't reach the input connection, we will call loadKeyboard again later, // so we need to save its state now. The call will be done in #retryResetCaches. @@ -842,7 +844,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } else if (restarting) { // TODO: Come up with a more comprehensive way to reset the keyboard layout when // a keyboard layout set doesn't get reloaded in this method. - switcher.resetKeyboardStateToAlphabet(); + switcher.resetKeyboardStateToAlphabet(getCurrentAutoCapsState(), + getCurrentRecapitalizeState()); // In apps like Talk, we come here when the text is sent and the field gets emptied and // we need to re-evaluate the shift state, but not the whole layout which would be // disruptive. @@ -1119,17 +1122,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mKeyPreviewBackingView.setVisibility(isFullscreenMode() ? View.GONE : View.VISIBLE); } - // Called from the KeyboardSwitcher which needs to know auto caps state to display - // the right layout. - // TODO[IL]: Remove this, pass the input logic to the keyboard switcher instead? - public int getCurrentAutoCapsState() { + private int getCurrentAutoCapsState() { return mInputLogic.getCurrentAutoCapsState(mSettings.getCurrent()); } - // Called from the KeyboardSwitcher which needs to know recaps state to display - // the right layout. - // TODO[IL]: Remove this, pass the input logic to the keyboard switcher instead? - public int getCurrentRecapitalizeState() { + private int getCurrentRecapitalizeState() { return mInputLogic.getCurrentRecapitalizeState(); } @@ -1224,7 +1221,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Implementation of {@link KeyboardActionListener}. @Override - public void onCodeInput(final int codePoint, final int x, final int y) { + public void onCodeInput(final int codePoint, final int x, final int y, + final boolean isKeyRepeat) { final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView(); // x and y include some padding, but everything down the line (especially native // code) needs the coordinates in the keyboard frame. @@ -1250,18 +1248,19 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mSubtypeSwitcher.switchToShortcutIME(this); // Still call the *#onCodeInput methods for readability. } - final Event event = createSoftwareKeypressEvent(codeToSend, keyX, keyY); + final Event event = createSoftwareKeypressEvent(codeToSend, keyX, keyY, isKeyRepeat); final InputTransaction completeInputTransaction = mInputLogic.onCodeInput(mSettings.getCurrent(), event, mKeyboardSwitcher.getKeyboardShiftMode(), mHandler); updateStateAfterInputTransaction(completeInputTransaction); - mKeyboardSwitcher.onCodeInput(codePoint, getCurrentAutoCapsState()); + mKeyboardSwitcher.onCodeInput(codePoint, getCurrentAutoCapsState(), + getCurrentRecapitalizeState()); } // A helper method to split the code point and the key code. Ultimately, they should not be // squashed into the same variable, and this method should be removed. private static Event createSoftwareKeypressEvent(final int keyCodeOrCodePoint, final int keyX, - final int keyY) { + final int keyY, final boolean isKeyRepeat) { final int keyCode; final int codePoint; if (keyCodeOrCodePoint <= 0) { @@ -1271,7 +1270,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen keyCode = Event.NOT_A_KEY_CODE; codePoint = keyCodeOrCodePoint; } - return Event.createSoftwareKeypressEvent(codePoint, keyCode, keyX, keyY); + return Event.createSoftwareKeypressEvent(codePoint, keyCode, keyX, keyY, isKeyRepeat); } // Called from PointerTracker through the KeyboardActionListener interface @@ -1282,7 +1281,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mInputLogic.onTextInput(mSettings.getCurrent(), event, mHandler); mKeyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(), getCurrentRecapitalizeState()); - mKeyboardSwitcher.onCodeInput(Constants.CODE_OUTPUT_TEXT, getCurrentAutoCapsState()); + mKeyboardSwitcher.onCodeInput(Constants.CODE_OUTPUT_TEXT, getCurrentAutoCapsState(), + getCurrentRecapitalizeState()); } @Override @@ -1320,7 +1320,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen @Override public void onFinishSlidingInput() { // User finished sliding input. - mKeyboardSwitcher.onFinishSlidingInput(); + mKeyboardSwitcher.onFinishSlidingInput(getCurrentAutoCapsState(), + getCurrentRecapitalizeState()); } // Called from PointerTracker through the KeyboardActionListener interface @@ -1509,7 +1510,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen loadSettings(); if (mKeyboardSwitcher.getMainKeyboardView() != null) { // Reload keyboard because the current language has been changed. - mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettings.getCurrent()); + mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettings.getCurrent(), + getCurrentAutoCapsState(), getCurrentRecapitalizeState()); } } @@ -1566,7 +1568,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen @Override public void onPressKey(final int primaryCode, final int repeatCount, final boolean isSinglePointer) { - mKeyboardSwitcher.onPressKey(primaryCode, isSinglePointer, getCurrentAutoCapsState()); + mKeyboardSwitcher.onPressKey(primaryCode, isSinglePointer, getCurrentAutoCapsState(), + getCurrentRecapitalizeState()); hapticAndAudioFeedback(primaryCode, repeatCount); } @@ -1574,7 +1577,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // press matching call is {@link #onPressKey(int,int,boolean)} above. @Override public void onReleaseKey(final int primaryCode, final boolean withSliding) { - mKeyboardSwitcher.onReleaseKey(primaryCode, withSliding); + mKeyboardSwitcher.onReleaseKey(primaryCode, withSliding, getCurrentAutoCapsState(), + getCurrentRecapitalizeState()); // If accessibility is on, ensure the user receives keyboard state updates. if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) { diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index bf8467eb6..491d98074 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -884,10 +884,17 @@ public final class InputLogic { mSpaceState = SpaceState.NONE; mDeleteCount++; - // In many cases, we may have to put the keyboard in auto-shift state again. However - // we want to wait a few milliseconds before doing it to avoid the keyboard flashing - // during key repeat. - inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_LATER); + // In many cases after backspace, we need to update the shift state. Normally we need + // to do this right away to avoid the shift state being out of date in case the user types + // backspace then some other character very fast. However, in the case of backspace key + // repeat, this can lead to flashiness when the cursor flies over positions where the + // shift state should be updated, so if this is a key repeat, we update after a small delay. + // Then again, even in the case of a key repeat, if the cursor is at start of text, it + // can't go any further back, so we can update right away even if it's a key repeat. + final int shiftUpdateKind = + inputTransaction.mEvent.isKeyRepeat() && mConnection.getExpectedSelectionStart() > 0 + ? InputTransaction.SHIFT_UPDATE_LATER : InputTransaction.SHIFT_UPDATE_NOW; + inputTransaction.requireShiftUpdate(shiftUpdateKind); if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { // If we are in the middle of a recorrection, we need to commit the recorrection @@ -910,11 +917,6 @@ public final class InputLogic { } mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); inputTransaction.setRequiresUpdateSuggestions(); - if (!mWordComposer.isComposingWord()) { - // If we just removed the last character, auto-caps mode may have changed so we - // need to re-evaluate. - inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW); - } } else { if (mLastComposedWord.canRevertCommit()) { if (inputTransaction.mSettingsValues.mIsInternal) { @@ -1025,8 +1027,6 @@ public final class InputLogic { restartSuggestionsOnWordTouchedByCursor(inputTransaction.mSettingsValues, true /* includeResumedWordInSuggestions */); } - // We just removed at least one character. We need to update the auto-caps state. - inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW); } } |