Fix updating the shift state upon backspace
Bug: 13514349 Change-Id: If4c9db12b0ab5be676f7a2f72715f469066ee537
This commit is contained in:
parent
30d5ed67d6
commit
2282e8520a
12 changed files with 99 additions and 45 deletions
|
@ -52,12 +52,16 @@ public class DeadKeyCombiner implements Combiner {
|
||||||
// how dead keys work).
|
// how dead keys work).
|
||||||
// If the event is a space, we should commit the dead char alone, but if it's
|
// If the event is a space, we should commit the dead char alone, but if it's
|
||||||
// not, we need to commit both.
|
// 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,
|
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 {
|
} else {
|
||||||
// We could combine the characters.
|
// We could combine the characters.
|
||||||
return Event.createHardwareKeypressEvent(resultingCodePoint, event.mKeyCode,
|
return Event.createHardwareKeypressEvent(resultingCodePoint, event.mKeyCode,
|
||||||
null /* next */);
|
null /* next */, false /* isKeyRepeat */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,8 @@ public class Event {
|
||||||
// This event is a dead character, usually input by a dead key. Examples include dead-acute
|
// This event is a dead character, usually input by a dead key. Examples include dead-acute
|
||||||
// or dead-abovering.
|
// or dead-abovering.
|
||||||
final private static int FLAG_DEAD = 0x1;
|
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
|
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
|
// 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,
|
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,
|
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,
|
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,
|
return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode,
|
||||||
Constants.EXTERNAL_KEYBOARD_COORDINATE, Constants.EXTERNAL_KEYBOARD_COORDINATE,
|
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}
|
// 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);
|
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
|
// Returns whether this is a fake key press from the suggestion strip. This happens with
|
||||||
// punctuation signs selected from the suggestion strip.
|
// punctuation signs selected from the suggestion strip.
|
||||||
public boolean isSuggestionStripPress() {
|
public boolean isSuggestionStripPress() {
|
||||||
|
|
|
@ -46,9 +46,10 @@ public class HardwareKeyboardEventDecoder implements HardwareEventDecoder {
|
||||||
// do not necessarily map to a unicode character. This represents a physical key, like
|
// 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.
|
// the key for 'A' or Space, but also Backspace or Ctrl or Caps Lock.
|
||||||
final int keyCode = keyEvent.getKeyCode();
|
final int keyCode = keyEvent.getKeyCode();
|
||||||
|
final boolean isKeyRepeat = (0 != keyEvent.getRepeatCount());
|
||||||
if (KeyEvent.KEYCODE_DEL == keyCode) {
|
if (KeyEvent.KEYCODE_DEL == keyCode) {
|
||||||
return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT, Constants.CODE_DELETE,
|
return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT, Constants.CODE_DELETE,
|
||||||
null /* next */);
|
null /* next */, isKeyRepeat);
|
||||||
}
|
}
|
||||||
if (keyEvent.isPrintingKey() || KeyEvent.KEYCODE_SPACE == keyCode
|
if (keyEvent.isPrintingKey() || KeyEvent.KEYCODE_SPACE == keyCode
|
||||||
|| KeyEvent.KEYCODE_ENTER == keyCode) {
|
|| KeyEvent.KEYCODE_ENTER == keyCode) {
|
||||||
|
@ -65,15 +66,16 @@ public class HardwareKeyboardEventDecoder implements HardwareEventDecoder {
|
||||||
// Latin IME decide what to do with it.
|
// Latin IME decide what to do with it.
|
||||||
if (keyEvent.isShiftPressed()) {
|
if (keyEvent.isShiftPressed()) {
|
||||||
return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT,
|
return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT,
|
||||||
Constants.CODE_SHIFT_ENTER, null /* next */);
|
Constants.CODE_SHIFT_ENTER, null /* next */, isKeyRepeat);
|
||||||
} else {
|
} else {
|
||||||
return Event.createHardwareKeypressEvent(Constants.CODE_ENTER, keyCode,
|
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
|
// 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.
|
// 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();
|
return Event.createNotHandledEvent();
|
||||||
}
|
}
|
||||||
|
|
|
@ -606,7 +606,8 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final int code = (Integer) tag;
|
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 */);
|
mKeyboardActionListener.onReleaseKey(code, false /* withSliding */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -634,7 +635,8 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
|
||||||
if (code == Constants.CODE_OUTPUT_TEXT) {
|
if (code == Constants.CODE_OUTPUT_TEXT) {
|
||||||
mKeyboardActionListener.onTextInput(key.getOutputText());
|
mKeyboardActionListener.onTextInput(key.getOutputText());
|
||||||
} else {
|
} 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 */);
|
mKeyboardActionListener.onReleaseKey(code, false /* withSliding */);
|
||||||
}
|
}
|
||||||
|
@ -901,8 +903,8 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleKeyUp() {
|
private void handleKeyUp() {
|
||||||
mKeyboardActionListener.onCodeInput(
|
mKeyboardActionListener.onCodeInput(Constants.CODE_DELETE,
|
||||||
Constants.CODE_DELETE, NOT_A_COORDINATE, NOT_A_COORDINATE);
|
NOT_A_COORDINATE, NOT_A_COORDINATE, false /* isKeyRepeat */);
|
||||||
mKeyboardActionListener.onReleaseKey(
|
mKeyboardActionListener.onReleaseKey(
|
||||||
Constants.CODE_DELETE, false /* withSliding */);
|
Constants.CODE_DELETE, false /* withSliding */);
|
||||||
++mRepeatCount;
|
++mRepeatCount;
|
||||||
|
|
|
@ -53,8 +53,10 @@ public interface KeyboardActionListener {
|
||||||
* {@link PointerTracker} or so, the value should be
|
* {@link PointerTracker} or so, the value should be
|
||||||
* {@link Constants#NOT_A_COORDINATE}.If it's called on insertion from the
|
* {@link Constants#NOT_A_COORDINATE}.If it's called on insertion from the
|
||||||
* suggestion strip, it should be {@link Constants#SUGGESTION_STRIP_COORDINATE}.
|
* 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.
|
* Sends a string of characters to the listener.
|
||||||
|
@ -107,7 +109,7 @@ public interface KeyboardActionListener {
|
||||||
@Override
|
@Override
|
||||||
public void onReleaseKey(int primaryCode, boolean withSliding) {}
|
public void onReleaseKey(int primaryCode, boolean withSliding) {}
|
||||||
@Override
|
@Override
|
||||||
public void onCodeInput(int primaryCode, int x, int y) {}
|
public void onCodeInput(int primaryCode, int x, int y, boolean isKeyRepeat) {}
|
||||||
@Override
|
@Override
|
||||||
public void onTextInput(String text) {}
|
public void onTextInput(String text) {}
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -626,8 +626,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
|
||||||
final int moreKeyCode = key.getMoreKeys()[0].mCode;
|
final int moreKeyCode = key.getMoreKeys()[0].mCode;
|
||||||
tracker.onLongPressed();
|
tracker.onLongPressed();
|
||||||
listener.onPressKey(moreKeyCode, 0 /* repeatCount */, true /* isSinglePointer */);
|
listener.onPressKey(moreKeyCode, 0 /* repeatCount */, true /* isSinglePointer */);
|
||||||
listener.onCodeInput(moreKeyCode,
|
listener.onCodeInput(moreKeyCode, Constants.NOT_A_COORDINATE,
|
||||||
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
|
Constants.NOT_A_COORDINATE, false /* isKeyRepeat */);
|
||||||
listener.onReleaseKey(moreKeyCode, false /* withSliding */);
|
listener.onReleaseKey(moreKeyCode, false /* withSliding */);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,9 +143,10 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel
|
||||||
mListener.onTextInput(mCurrentKey.getOutputText());
|
mListener.onTextInput(mCurrentKey.getOutputText());
|
||||||
} else if (code != Constants.CODE_UNSPECIFIED) {
|
} else if (code != Constants.CODE_UNSPECIFIED) {
|
||||||
if (getKeyboard().hasProximityCharsCorrection(code)) {
|
if (getKeyboard().hasProximityCharsCorrection(code)) {
|
||||||
mListener.onCodeInput(code, x, y);
|
mListener.onCodeInput(code, x, y, false /* isKeyRepeat */);
|
||||||
} else {
|
} 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 */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
// Note that we need primaryCode argument because the keyboard may in shifted state and the
|
||||||
// primaryCode is different from {@link Key#mKeyCode}.
|
// primaryCode is different from {@link Key#mKeyCode}.
|
||||||
private void callListenerOnCodeInput(final Key key, final int primaryCode, final int x,
|
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 ignoreModifierKey = mIsInDraggingFinger && key.isModifier();
|
||||||
final boolean altersCode = key.altCodeWhileTyping() && sTimerProxy.isTypingState();
|
final boolean altersCode = key.altCodeWhileTyping() && sTimerProxy.isTypingState();
|
||||||
final int code = altersCode ? key.getAltCode() : primaryCode;
|
final int code = altersCode ? key.getAltCode() : primaryCode;
|
||||||
|
@ -350,10 +350,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
|
||||||
sListener.onTextInput(key.getOutputText());
|
sListener.onTextInput(key.getOutputText());
|
||||||
} else if (code != Constants.CODE_UNSPECIFIED) {
|
} else if (code != Constants.CODE_UNSPECIFIED) {
|
||||||
if (mKeyboard.hasProximityCharsCorrection(code)) {
|
if (mKeyboard.hasProximityCharsCorrection(code)) {
|
||||||
sListener.onCodeInput(code, x, y);
|
sListener.onCodeInput(code, x, y, isKeyRepeat);
|
||||||
} else {
|
} else {
|
||||||
sListener.onCodeInput(code,
|
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();
|
final int code = key.getCode();
|
||||||
callListenerOnCodeInput(key, code, x, y, eventTime);
|
callListenerOnCodeInput(key, code, x, y, eventTime, false /* isKeyRepeat */);
|
||||||
callListenerOnRelease(key, code, false /* withSliding */);
|
callListenerOnRelease(key, code, false /* withSliding */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1229,7 +1229,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
|
||||||
final int nextRepeatCount = repeatCount + 1;
|
final int nextRepeatCount = repeatCount + 1;
|
||||||
startKeyRepeatTimer(nextRepeatCount);
|
startKeyRepeatTimer(nextRepeatCount);
|
||||||
callListenerOnPressAndCheckKeyboardLayoutChange(key, repeatCount);
|
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) {
|
private void startKeyRepeatTimer(final int repeatCount) {
|
||||||
|
|
|
@ -1224,7 +1224,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
|
|
||||||
// Implementation of {@link KeyboardActionListener}.
|
// Implementation of {@link KeyboardActionListener}.
|
||||||
@Override
|
@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();
|
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
|
||||||
// x and y include some padding, but everything down the line (especially native
|
// x and y include some padding, but everything down the line (especially native
|
||||||
// code) needs the coordinates in the keyboard frame.
|
// code) needs the coordinates in the keyboard frame.
|
||||||
|
@ -1250,7 +1251,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
mSubtypeSwitcher.switchToShortcutIME(this);
|
mSubtypeSwitcher.switchToShortcutIME(this);
|
||||||
// Still call the *#onCodeInput methods for readability.
|
// 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 =
|
final InputTransaction completeInputTransaction =
|
||||||
mInputLogic.onCodeInput(mSettings.getCurrent(), event,
|
mInputLogic.onCodeInput(mSettings.getCurrent(), event,
|
||||||
mKeyboardSwitcher.getKeyboardShiftMode(), mHandler);
|
mKeyboardSwitcher.getKeyboardShiftMode(), mHandler);
|
||||||
|
@ -1261,7 +1262,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
// A helper method to split the code point and the key code. Ultimately, they should not be
|
// 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.
|
// squashed into the same variable, and this method should be removed.
|
||||||
private static Event createSoftwareKeypressEvent(final int keyCodeOrCodePoint, final int keyX,
|
private static Event createSoftwareKeypressEvent(final int keyCodeOrCodePoint, final int keyX,
|
||||||
final int keyY) {
|
final int keyY, final boolean isKeyRepeat) {
|
||||||
final int keyCode;
|
final int keyCode;
|
||||||
final int codePoint;
|
final int codePoint;
|
||||||
if (keyCodeOrCodePoint <= 0) {
|
if (keyCodeOrCodePoint <= 0) {
|
||||||
|
@ -1271,7 +1272,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
keyCode = Event.NOT_A_KEY_CODE;
|
keyCode = Event.NOT_A_KEY_CODE;
|
||||||
codePoint = keyCodeOrCodePoint;
|
codePoint = keyCodeOrCodePoint;
|
||||||
}
|
}
|
||||||
return Event.createSoftwareKeypressEvent(codePoint, keyCode, keyX, keyY);
|
return Event.createSoftwareKeypressEvent(codePoint, keyCode, keyX, keyY, isKeyRepeat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from PointerTracker through the KeyboardActionListener interface
|
// Called from PointerTracker through the KeyboardActionListener interface
|
||||||
|
|
|
@ -884,10 +884,17 @@ public final class InputLogic {
|
||||||
mSpaceState = SpaceState.NONE;
|
mSpaceState = SpaceState.NONE;
|
||||||
mDeleteCount++;
|
mDeleteCount++;
|
||||||
|
|
||||||
// In many cases, we may have to put the keyboard in auto-shift state again. However
|
// In many cases after backspace, we need to update the shift state. Normally we need
|
||||||
// we want to wait a few milliseconds before doing it to avoid the keyboard flashing
|
// to do this right away to avoid the shift state being out of date in case the user types
|
||||||
// during key repeat.
|
// backspace then some other character very fast. However, in the case of backspace key
|
||||||
inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_LATER);
|
// 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 (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
|
||||||
// If we are in the middle of a recorrection, we need to commit the recorrection
|
// 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);
|
mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
|
||||||
inputTransaction.setRequiresUpdateSuggestions();
|
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 {
|
} else {
|
||||||
if (mLastComposedWord.canRevertCommit()) {
|
if (mLastComposedWord.canRevertCommit()) {
|
||||||
if (inputTransaction.mSettingsValues.mIsInternal) {
|
if (inputTransaction.mSettingsValues.mIsInternal) {
|
||||||
|
@ -1025,8 +1027,6 @@ public final class InputLogic {
|
||||||
restartSuggestionsOnWordTouchedByCursor(inputTransaction.mSettingsValues,
|
restartSuggestionsOnWordTouchedByCursor(inputTransaction.mSettingsValues,
|
||||||
true /* includeResumedWordInSuggestions */);
|
true /* includeResumedWordInSuggestions */);
|
||||||
}
|
}
|
||||||
// We just removed at least one character. We need to update the auto-caps state.
|
|
||||||
inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -254,7 +254,7 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// type(int) and type(String): helper methods to send a code point resp. a string to LatinIME.
|
// type(int) and type(String): helper methods to send a code point resp. a string to LatinIME.
|
||||||
protected void type(final int codePoint) {
|
protected void typeInternal(final int codePoint, final boolean isKeyRepeat) {
|
||||||
// onPressKey and onReleaseKey are explicitly deactivated here, but they do happen in the
|
// onPressKey and onReleaseKey are explicitly deactivated here, but they do happen in the
|
||||||
// code (although multitouch/slide input and other factors make the sequencing complicated).
|
// code (although multitouch/slide input and other factors make the sequencing complicated).
|
||||||
// They are supposed to be entirely deconnected from the input logic from LatinIME point of
|
// They are supposed to be entirely deconnected from the input logic from LatinIME point of
|
||||||
|
@ -263,16 +263,26 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
|
||||||
// but keep them in mind if something breaks. Commenting them out as is should work.
|
// but keep them in mind if something breaks. Commenting them out as is should work.
|
||||||
//mLatinIME.onPressKey(codePoint, 0 /* repeatCount */, true /* isSinglePointer */);
|
//mLatinIME.onPressKey(codePoint, 0 /* repeatCount */, true /* isSinglePointer */);
|
||||||
final Key key = mKeyboard.getKey(codePoint);
|
final Key key = mKeyboard.getKey(codePoint);
|
||||||
if (key != null) {
|
if (key == null) {
|
||||||
|
mLatinIME.onCodeInput(codePoint, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
|
||||||
|
isKeyRepeat);
|
||||||
|
} else {
|
||||||
final int x = key.getX() + key.getWidth() / 2;
|
final int x = key.getX() + key.getWidth() / 2;
|
||||||
final int y = key.getY() + key.getHeight() / 2;
|
final int y = key.getY() + key.getHeight() / 2;
|
||||||
mLatinIME.onCodeInput(codePoint, x, y);
|
mLatinIME.onCodeInput(codePoint, x, y, isKeyRepeat);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
mLatinIME.onCodeInput(codePoint, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
|
// Also see the comment at the top of this function about onReleaseKey
|
||||||
//mLatinIME.onReleaseKey(codePoint, false /* withSliding */);
|
//mLatinIME.onReleaseKey(codePoint, false /* withSliding */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void type(final int codePoint) {
|
||||||
|
typeInternal(codePoint, false /* isKeyRepeat */);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void repeatKey(final int codePoint) {
|
||||||
|
typeInternal(codePoint, true /* isKeyRepeat */);
|
||||||
|
}
|
||||||
|
|
||||||
protected void type(final String stringToType) {
|
protected void type(final String stringToType) {
|
||||||
for (int i = 0; i < stringToType.length(); i = stringToType.offsetByCodePoints(i, 1)) {
|
for (int i = 0; i < stringToType.length(); i = stringToType.offsetByCodePoints(i, 1)) {
|
||||||
type(stringToType.codePointAt(i));
|
type(stringToType.codePointAt(i));
|
||||||
|
|
|
@ -53,4 +53,29 @@ public class ShiftModeTests extends InputTestsBase {
|
||||||
type(" ");
|
type(" ");
|
||||||
assertTrue("Caps after period space", isCapsModeAutoShifted());
|
assertTrue("Caps after period space", isCapsModeAutoShifted());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testBackspace() {
|
||||||
|
assertTrue("Initial auto caps state", isCapsModeAutoShifted());
|
||||||
|
type("A");
|
||||||
|
assertFalse("Caps state after one letter", isCapsModeAutoShifted());
|
||||||
|
type(Constants.CODE_DELETE);
|
||||||
|
assertTrue("Auto caps state at start after delete", isCapsModeAutoShifted());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRepeatingBackspace() {
|
||||||
|
final String SENTENCE_TO_TYPE = "Test sentence. Another.";
|
||||||
|
final int BACKSPACE_COUNT =
|
||||||
|
SENTENCE_TO_TYPE.length() - SENTENCE_TO_TYPE.lastIndexOf(' ') - 1;
|
||||||
|
|
||||||
|
type(SENTENCE_TO_TYPE);
|
||||||
|
assertFalse("Caps after typing \"" + SENTENCE_TO_TYPE + "\"", isCapsModeAutoShifted());
|
||||||
|
type(Constants.CODE_DELETE);
|
||||||
|
for (int i = 1; i < BACKSPACE_COUNT; ++i) {
|
||||||
|
repeatKey(Constants.CODE_DELETE);
|
||||||
|
}
|
||||||
|
assertFalse("Caps immediately after repeating Backspace a lot", isCapsModeAutoShifted());
|
||||||
|
sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
|
||||||
|
runMessages();
|
||||||
|
assertTrue("Caps after a while after repeating Backspace a lot", isCapsModeAutoShifted());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue