am 0e82fa27: [IL3] Move handleBackspace to InputLogic.
* commit '0e82fa273d09f781d88a8d222394c7bcc7827745': [IL3] Move handleBackspace to InputLogic.main
commit
be944b87ab
|
@ -156,6 +156,8 @@ public final class Constants {
|
||||||
|
|
||||||
// Key events coming any faster than this are long-presses.
|
// Key events coming any faster than this are long-presses.
|
||||||
public static final int LONG_PRESS_MILLISECONDS = 200;
|
public static final int LONG_PRESS_MILLISECONDS = 200;
|
||||||
|
// How many continuous deletes at which to start deleting at a higher speed.
|
||||||
|
public static final int DELETE_ACCELERATE_AT = 20;
|
||||||
|
|
||||||
public static boolean isValidCoordinate(final int coordinate) {
|
public static boolean isValidCoordinate(final int coordinate) {
|
||||||
// Detect {@link NOT_A_COORDINATE}, {@link SUGGESTION_STRIP_COORDINATE},
|
// Detect {@link NOT_A_COORDINATE}, {@link SUGGESTION_STRIP_COORDINATE},
|
||||||
|
|
|
@ -121,9 +121,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
|
|
||||||
private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100;
|
private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100;
|
||||||
|
|
||||||
// How many continuous deletes at which to start deleting at a higher speed.
|
|
||||||
private static final int DELETE_ACCELERATE_AT = 20;
|
|
||||||
|
|
||||||
private static final int PENDING_IMS_CALLBACK_DURATION = 800;
|
private static final int PENDING_IMS_CALLBACK_DURATION = 800;
|
||||||
|
|
||||||
private static final int PERIOD_FOR_AUDIO_AND_HAPTIC_FEEDBACK_IN_KEY_REPEAT = 2;
|
private static final int PERIOD_FOR_AUDIO_AND_HAPTIC_FEEDBACK_IN_KEY_REPEAT = 2;
|
||||||
|
@ -145,7 +142,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
private SuggestionStripView mSuggestionStripView;
|
private SuggestionStripView mSuggestionStripView;
|
||||||
|
|
||||||
private CompletionInfo[] mApplicationSpecifiedCompletions;
|
private CompletionInfo[] mApplicationSpecifiedCompletions;
|
||||||
private AppWorkaroundsUtils mAppWorkAroundsUtils = new AppWorkaroundsUtils();
|
// TODO[IL]: Make this an AsyncResultHolder or a Future in SettingsValues
|
||||||
|
public AppWorkaroundsUtils mAppWorkAroundsUtils = new AppWorkaroundsUtils();
|
||||||
|
|
||||||
private RichInputMethodManager mRichImm;
|
private RichInputMethodManager mRichImm;
|
||||||
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
|
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
|
||||||
|
@ -160,8 +158,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
private boolean mUseOnlyPersonalizationDictionaryForDebug = false;
|
private boolean mUseOnlyPersonalizationDictionaryForDebug = false;
|
||||||
private boolean mBoostPersonalizationDictionaryForDebug = false;
|
private boolean mBoostPersonalizationDictionaryForDebug = false;
|
||||||
|
|
||||||
// Member variables for remembering the current device orientation.
|
// Member variable for remembering the current device orientation.
|
||||||
private int mDisplayOrientation;
|
// TODO[IL]: Move this to SettingsValues.
|
||||||
|
public int mDisplayOrientation;
|
||||||
|
|
||||||
// Object for reacting to adding/removing a dictionary pack.
|
// Object for reacting to adding/removing a dictionary pack.
|
||||||
private BroadcastReceiver mDictionaryPackInstallReceiver =
|
private BroadcastReceiver mDictionaryPackInstallReceiver =
|
||||||
|
@ -784,7 +783,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
// The app calling setText() has the effect of clearing the composing
|
// The app calling setText() has the effect of clearing the composing
|
||||||
// span, so we should reset our state unconditionally, even if restarting is true.
|
// span, so we should reset our state unconditionally, even if restarting is true.
|
||||||
mInputLogic.mEnteredText = null;
|
mInputLogic.mEnteredText = null;
|
||||||
resetComposingState(true /* alsoResetLastComposedWord */);
|
mInputLogic.resetComposingState(true /* alsoResetLastComposedWord */);
|
||||||
mInputLogic.mDeleteCount = 0;
|
mInputLogic.mDeleteCount = 0;
|
||||||
mInputLogic.mSpaceState = SpaceState.NONE;
|
mInputLogic.mSpaceState = SpaceState.NONE;
|
||||||
mInputLogic.mRecapitalizeStatus.deactivate();
|
mInputLogic.mRecapitalizeStatus.deactivate();
|
||||||
|
@ -965,7 +964,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
if (mInputLogic.mWordComposer.isComposingWord()) {
|
if (mInputLogic.mWordComposer.isComposingWord()) {
|
||||||
mInputLogic.mConnection.finishComposingText();
|
mInputLogic.mConnection.finishComposingText();
|
||||||
}
|
}
|
||||||
resetComposingState(true /* alsoResetLastComposedWord */);
|
mInputLogic.resetComposingState(true /* alsoResetLastComposedWord */);
|
||||||
// Notify ResearchLogger
|
// Notify ResearchLogger
|
||||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||||
ResearchLogger.latinIME_onFinishInputViewInternal(finishingInput,
|
ResearchLogger.latinIME_onFinishInputViewInternal(finishingInput,
|
||||||
|
@ -1041,7 +1040,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
// Another option would be to send suggestions each time we set the composing
|
// Another option would be to send suggestions each time we set the composing
|
||||||
// text, but that is probably too expensive to do, so we decided to leave things
|
// text, but that is probably too expensive to do, so we decided to leave things
|
||||||
// as is.
|
// as is.
|
||||||
resetEntireInputState(newSelStart, newSelEnd);
|
mInputLogic.resetEntireInputState(mSettings.getCurrent(), newSelStart, newSelEnd);
|
||||||
} else {
|
} else {
|
||||||
// resetEntireInputState calls resetCachesUponCursorMove, but forcing the
|
// resetEntireInputState calls resetCachesUponCursorMove, but forcing the
|
||||||
// composition to end. But in all cases where we don't reset the entire input
|
// composition to end. But in all cases where we don't reset the entire input
|
||||||
|
@ -1268,28 +1267,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
mKeyPreviewBackingView.setVisibility(isFullscreenMode() ? View.GONE : View.VISIBLE);
|
mKeyPreviewBackingView.setVisibility(isFullscreenMode() ? View.GONE : View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will reset the whole input state to the starting state. It will clear
|
|
||||||
// the composing word, reset the last composed word, tell the inputconnection about it.
|
|
||||||
private void resetEntireInputState(final int newSelStart, final int newSelEnd) {
|
|
||||||
final boolean shouldFinishComposition = mInputLogic.mWordComposer.isComposingWord();
|
|
||||||
resetComposingState(true /* alsoResetLastComposedWord */);
|
|
||||||
final SettingsValues settingsValues = mSettings.getCurrent();
|
|
||||||
if (settingsValues.mBigramPredictionEnabled) {
|
|
||||||
clearSuggestionStrip();
|
|
||||||
} else {
|
|
||||||
setSuggestedWords(settingsValues.mSuggestPuncList, false);
|
|
||||||
}
|
|
||||||
mInputLogic.mConnection.resetCachesUponCursorMoveAndReturnSuccess(newSelStart, newSelEnd,
|
|
||||||
shouldFinishComposition);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetComposingState(final boolean alsoResetLastComposedWord) {
|
|
||||||
mInputLogic.mWordComposer.reset();
|
|
||||||
if (alsoResetLastComposedWord) {
|
|
||||||
mInputLogic.mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void commitTyped(final String separatorString) {
|
private void commitTyped(final String separatorString) {
|
||||||
if (!mInputLogic.mWordComposer.isComposingWord()) return;
|
if (!mInputLogic.mWordComposer.isComposingWord()) return;
|
||||||
final String typedWord = mInputLogic.mWordComposer.getTypedWord();
|
final String typedWord = mInputLogic.mWordComposer.getTypedWord();
|
||||||
|
@ -1459,38 +1436,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
mSubtypeState.switchSubtype(token, mRichImm);
|
mSubtypeState.switchSubtype(token, mRichImm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendDownUpKeyEvent(final int code) {
|
|
||||||
final long eventTime = SystemClock.uptimeMillis();
|
|
||||||
mInputLogic.mConnection.sendKeyEvent(new KeyEvent(eventTime, eventTime,
|
|
||||||
KeyEvent.ACTION_DOWN, code, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
|
|
||||||
KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));
|
|
||||||
mInputLogic.mConnection.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime,
|
|
||||||
KeyEvent.ACTION_UP, code, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
|
|
||||||
KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendKeyCodePoint(final int code) {
|
|
||||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
|
||||||
ResearchLogger.latinIME_sendKeyCodePoint(code);
|
|
||||||
}
|
|
||||||
// TODO: Remove this special handling of digit letters.
|
|
||||||
// For backward compatibility. See {@link InputMethodService#sendKeyChar(char)}.
|
|
||||||
if (code >= '0' && code <= '9') {
|
|
||||||
sendDownUpKeyEvent(code - '0' + KeyEvent.KEYCODE_0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Constants.CODE_ENTER == code && mAppWorkAroundsUtils.isBeforeJellyBean()) {
|
|
||||||
// Backward compatibility mode. Before Jelly bean, the keyboard would simulate
|
|
||||||
// a hardware keyboard event on pressing enter or delete. This is bad for many
|
|
||||||
// reasons (there are race conditions with commits) but some applications are
|
|
||||||
// relying on this behavior so we continue to support it for older apps.
|
|
||||||
sendDownUpKeyEvent(KeyEvent.KEYCODE_ENTER);
|
|
||||||
} else {
|
|
||||||
mInputLogic.mConnection.commitText(StringUtils.newSingleCodePointString(code), 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementation of {@link KeyboardActionListener}.
|
// Implementation of {@link KeyboardActionListener}.
|
||||||
@Override
|
@Override
|
||||||
public void onCodeInput(final int primaryCode, final int x, final int y) {
|
public void onCodeInput(final int primaryCode, final int x, final int y) {
|
||||||
|
@ -1520,8 +1465,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
if (mInputLogic.mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
|
if (mInputLogic.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
|
||||||
// first so that we can insert the character at the current cursor position.
|
// first so that we can insert the character at the current cursor position.
|
||||||
resetEntireInputState(mInputLogic.mLastSelectionStart,
|
mInputLogic.resetEntireInputState(settingsValues,
|
||||||
mInputLogic.mLastSelectionEnd);
|
mInputLogic.mLastSelectionStart, mInputLogic.mLastSelectionEnd);
|
||||||
} else {
|
} else {
|
||||||
commitTyped(LastComposedWord.NOT_A_SEPARATOR);
|
commitTyped(LastComposedWord.NOT_A_SEPARATOR);
|
||||||
}
|
}
|
||||||
|
@ -1547,7 +1492,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
if (mInputLogic.mWordComposer.isComposingWord()) {
|
if (mInputLogic.mWordComposer.isComposingWord()) {
|
||||||
commitCurrentAutoCorrection(rawText);
|
commitCurrentAutoCorrection(rawText);
|
||||||
} else {
|
} else {
|
||||||
resetComposingState(true /* alsoResetLastComposedWord */);
|
mInputLogic.resetComposingState(true /* alsoResetLastComposedWord */);
|
||||||
}
|
}
|
||||||
mHandler.postUpdateSuggestionStrip();
|
mHandler.postUpdateSuggestionStrip();
|
||||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS
|
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS
|
||||||
|
@ -1590,8 +1535,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
if (mInputLogic.mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
|
if (mInputLogic.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
|
||||||
// first so that we can insert the batch input at the current cursor position.
|
// first so that we can insert the batch input at the current cursor position.
|
||||||
resetEntireInputState(mInputLogic.mLastSelectionStart,
|
mInputLogic.resetEntireInputState(currentSettingsValues,
|
||||||
mInputLogic.mLastSelectionEnd);
|
mInputLogic.mLastSelectionStart, mInputLogic.mLastSelectionEnd);
|
||||||
} else if (wordComposerSize <= 1) {
|
} else if (wordComposerSize <= 1) {
|
||||||
// We auto-correct the previous (typed, not gestured) string iff it's one character
|
// We auto-correct the previous (typed, not gestured) string iff it's one character
|
||||||
// long. The reason for this is, even in the middle of gesture typing, you'll still
|
// long. The reason for this is, even in the middle of gesture typing, you'll still
|
||||||
|
@ -1886,156 +1831,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
mInputUpdater.onCancelBatchInput();
|
mInputUpdater.onCancelBatchInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO[IL]: Move this to InputLogic and make private again.
|
|
||||||
public void handleBackspace(final int spaceState) {
|
|
||||||
mInputLogic.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.
|
|
||||||
mHandler.postUpdateShiftState();
|
|
||||||
|
|
||||||
if (mInputLogic.mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
|
|
||||||
// If we are in the middle of a recorrection, we need to commit the recorrection
|
|
||||||
// first so that we can remove the character at the current cursor position.
|
|
||||||
resetEntireInputState(mInputLogic.mLastSelectionStart, mInputLogic.mLastSelectionEnd);
|
|
||||||
// When we exit this if-clause, mWordComposer.isComposingWord() will return false.
|
|
||||||
}
|
|
||||||
if (mInputLogic.mWordComposer.isComposingWord()) {
|
|
||||||
if (mInputLogic.mWordComposer.isBatchMode()) {
|
|
||||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
|
||||||
final String word = mInputLogic.mWordComposer.getTypedWord();
|
|
||||||
ResearchLogger.latinIME_handleBackspace_batch(word, 1);
|
|
||||||
}
|
|
||||||
final String rejectedSuggestion = mInputLogic.mWordComposer.getTypedWord();
|
|
||||||
mInputLogic.mWordComposer.reset();
|
|
||||||
mInputLogic.mWordComposer.setRejectedBatchModeSuggestion(rejectedSuggestion);
|
|
||||||
} else {
|
|
||||||
mInputLogic.mWordComposer.deleteLast();
|
|
||||||
}
|
|
||||||
mInputLogic.mConnection.setComposingText(getTextWithUnderline(
|
|
||||||
mInputLogic.mWordComposer.getTypedWord()), 1);
|
|
||||||
mHandler.postUpdateSuggestionStrip();
|
|
||||||
if (!mInputLogic.mWordComposer.isComposingWord()) {
|
|
||||||
// If we just removed the last character, auto-caps mode may have changed so we
|
|
||||||
// need to re-evaluate.
|
|
||||||
mKeyboardSwitcher.updateShiftState();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final SettingsValues currentSettings = mSettings.getCurrent();
|
|
||||||
if (mInputLogic.mLastComposedWord.canRevertCommit()) {
|
|
||||||
if (currentSettings.mIsInternal) {
|
|
||||||
LatinImeLoggerUtils.onAutoCorrectionCancellation();
|
|
||||||
}
|
|
||||||
revertCommit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mInputLogic.mEnteredText != null
|
|
||||||
&& mInputLogic.mConnection.sameAsTextBeforeCursor(mInputLogic.mEnteredText)) {
|
|
||||||
// Cancel multi-character input: remove the text we just entered.
|
|
||||||
// This is triggered on backspace after a key that inputs multiple characters,
|
|
||||||
// like the smiley key or the .com key.
|
|
||||||
mInputLogic.mConnection.deleteSurroundingText(
|
|
||||||
mInputLogic.mEnteredText.length(), 0);
|
|
||||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
|
||||||
ResearchLogger.latinIME_handleBackspace_cancelTextInput(
|
|
||||||
mInputLogic.mEnteredText);
|
|
||||||
}
|
|
||||||
mInputLogic.mEnteredText = null;
|
|
||||||
// If we have mEnteredText, then we know that mHasUncommittedTypedChars == false.
|
|
||||||
// In addition we know that spaceState is false, and that we should not be
|
|
||||||
// reverting any autocorrect at this point. So we can safely return.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (SpaceState.DOUBLE == spaceState) {
|
|
||||||
mHandler.cancelDoubleSpacePeriodTimer();
|
|
||||||
if (mInputLogic.mConnection.revertDoubleSpacePeriod()) {
|
|
||||||
// No need to reset mSpaceState, it has already be done (that's why we
|
|
||||||
// receive it as a parameter)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (SpaceState.SWAP_PUNCTUATION == spaceState) {
|
|
||||||
if (mInputLogic.mConnection.revertSwapPunctuation()) {
|
|
||||||
// Likewise
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No cancelling of commit/double space/swap: we have a regular backspace.
|
|
||||||
// We should backspace one char and restart suggestion if at the end of a word.
|
|
||||||
if (mInputLogic.mLastSelectionStart != mInputLogic.mLastSelectionEnd) {
|
|
||||||
// If there is a selection, remove it.
|
|
||||||
final int numCharsDeleted =
|
|
||||||
mInputLogic.mLastSelectionEnd - mInputLogic.mLastSelectionStart;
|
|
||||||
mInputLogic.mConnection.setSelection(mInputLogic.mLastSelectionEnd,
|
|
||||||
mInputLogic.mLastSelectionEnd);
|
|
||||||
// Reset mLastSelectionEnd to mLastSelectionStart. This is what is supposed to
|
|
||||||
// happen, and if it's wrong, the next call to onUpdateSelection will correct it,
|
|
||||||
// but we want to set it right away to avoid it being used with the wrong values
|
|
||||||
// later (typically, in a subsequent press on backspace).
|
|
||||||
mInputLogic.mLastSelectionEnd = mInputLogic.mLastSelectionStart;
|
|
||||||
mInputLogic.mConnection.deleteSurroundingText(numCharsDeleted, 0);
|
|
||||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
|
||||||
ResearchLogger.latinIME_handleBackspace(numCharsDeleted,
|
|
||||||
false /* shouldUncommitLogUnit */);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// There is no selection, just delete one character.
|
|
||||||
if (mInputLogic.NOT_A_CURSOR_POSITION == mInputLogic.mLastSelectionEnd) {
|
|
||||||
// This should never happen.
|
|
||||||
Log.e(TAG, "Backspace when we don't know the selection position");
|
|
||||||
}
|
|
||||||
if (mAppWorkAroundsUtils.isBeforeJellyBean() ||
|
|
||||||
currentSettings.mInputAttributes.isTypeNull()) {
|
|
||||||
// There are two possible reasons to send a key event: either the field has
|
|
||||||
// type TYPE_NULL, in which case the keyboard should send events, or we are
|
|
||||||
// running in backward compatibility mode. Before Jelly bean, the keyboard
|
|
||||||
// would simulate a hardware keyboard event on pressing enter or delete. This
|
|
||||||
// is bad for many reasons (there are race conditions with commits) but some
|
|
||||||
// applications are relying on this behavior so we continue to support it for
|
|
||||||
// older apps, so we retain this behavior if the app has target SDK < JellyBean.
|
|
||||||
sendDownUpKeyEvent(KeyEvent.KEYCODE_DEL);
|
|
||||||
if (mInputLogic.mDeleteCount > DELETE_ACCELERATE_AT) {
|
|
||||||
sendDownUpKeyEvent(KeyEvent.KEYCODE_DEL);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final int codePointBeforeCursor =
|
|
||||||
mInputLogic.mConnection.getCodePointBeforeCursor();
|
|
||||||
if (codePointBeforeCursor == Constants.NOT_A_CODE) {
|
|
||||||
// Nothing to delete before the cursor.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final int lengthToDelete =
|
|
||||||
Character.isSupplementaryCodePoint(codePointBeforeCursor) ? 2 : 1;
|
|
||||||
mInputLogic.mConnection.deleteSurroundingText(lengthToDelete, 0);
|
|
||||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
|
||||||
ResearchLogger.latinIME_handleBackspace(lengthToDelete,
|
|
||||||
true /* shouldUncommitLogUnit */);
|
|
||||||
}
|
|
||||||
if (mInputLogic.mDeleteCount > DELETE_ACCELERATE_AT) {
|
|
||||||
final int codePointBeforeCursorToDeleteAgain =
|
|
||||||
mInputLogic.mConnection.getCodePointBeforeCursor();
|
|
||||||
if (codePointBeforeCursorToDeleteAgain != Constants.NOT_A_CODE) {
|
|
||||||
final int lengthToDeleteAgain = Character.isSupplementaryCodePoint(
|
|
||||||
codePointBeforeCursorToDeleteAgain) ? 2 : 1;
|
|
||||||
mInputLogic.mConnection.deleteSurroundingText(lengthToDeleteAgain, 0);
|
|
||||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
|
||||||
ResearchLogger.latinIME_handleBackspace(lengthToDeleteAgain,
|
|
||||||
true /* shouldUncommitLogUnit */);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (currentSettings.isSuggestionsRequested(mDisplayOrientation)
|
|
||||||
&& currentSettings.mCurrentLanguageHasSpaces) {
|
|
||||||
restartSuggestionsOnWordBeforeCursorIfAtEndOfWord();
|
|
||||||
}
|
|
||||||
// We just removed a character. We need to update the auto-caps state.
|
|
||||||
mKeyboardSwitcher.updateShiftState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Strip a trailing space if necessary and returns whether it's a swap weak space situation.
|
* Strip a trailing space if necessary and returns whether it's a swap weak space situation.
|
||||||
*/
|
*/
|
||||||
|
@ -2076,7 +1871,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
if (mInputLogic.mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
|
if (mInputLogic.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
|
||||||
// first so that we can insert the character at the current cursor position.
|
// first so that we can insert the character at the current cursor position.
|
||||||
resetEntireInputState(mInputLogic.mLastSelectionStart, mInputLogic.mLastSelectionEnd);
|
mInputLogic.resetEntireInputState(currentSettings, mInputLogic.mLastSelectionStart,
|
||||||
|
mInputLogic.mLastSelectionEnd);
|
||||||
isComposingWord = false;
|
isComposingWord = false;
|
||||||
}
|
}
|
||||||
// We want to find out whether to start composing a new word with this character. If so,
|
// We want to find out whether to start composing a new word with this character. If so,
|
||||||
|
@ -2103,7 +1899,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
// when we commit this one, if we ever do; if on the other hand we backspace
|
// when we commit this one, if we ever do; if on the other hand we backspace
|
||||||
// it entirely and resume suggestions on the previous word, we'd like to still
|
// it entirely and resume suggestions on the previous word, we'd like to still
|
||||||
// have touch coordinates for it.
|
// have touch coordinates for it.
|
||||||
resetComposingState(false /* alsoResetLastComposedWord */);
|
mInputLogic.resetComposingState(false /* alsoResetLastComposedWord */);
|
||||||
}
|
}
|
||||||
if (isComposingWord) {
|
if (isComposingWord) {
|
||||||
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
|
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
|
||||||
|
@ -2120,13 +1916,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
getActualCapsMode(),
|
getActualCapsMode(),
|
||||||
getNthPreviousWordForSuggestion(currentSettings, 1 /* nthPreviousWord */));
|
getNthPreviousWordForSuggestion(currentSettings, 1 /* nthPreviousWord */));
|
||||||
}
|
}
|
||||||
mInputLogic.mConnection.setComposingText(getTextWithUnderline(
|
mInputLogic.mConnection.setComposingText(mInputLogic.getTextWithUnderline(
|
||||||
mInputLogic.mWordComposer.getTypedWord()), 1);
|
mInputLogic.mWordComposer.getTypedWord()), 1);
|
||||||
} else {
|
} else {
|
||||||
final boolean swapWeakSpace = maybeStripSpace(primaryCode, spaceState,
|
final boolean swapWeakSpace = maybeStripSpace(primaryCode, spaceState,
|
||||||
Constants.SUGGESTION_STRIP_COORDINATE == x);
|
Constants.SUGGESTION_STRIP_COORDINATE == x);
|
||||||
|
|
||||||
sendKeyCodePoint(primaryCode);
|
mInputLogic.sendKeyCodePoint(primaryCode);
|
||||||
|
|
||||||
if (swapWeakSpace) {
|
if (swapWeakSpace) {
|
||||||
swapSwapperAndSpace();
|
swapSwapperAndSpace();
|
||||||
|
@ -2200,7 +1996,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
if (mInputLogic.mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
|
if (mInputLogic.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
|
||||||
// first so that we can insert the separator at the current cursor position.
|
// first so that we can insert the separator at the current cursor position.
|
||||||
resetEntireInputState(mInputLogic.mLastSelectionStart, mInputLogic.mLastSelectionEnd);
|
mInputLogic.resetEntireInputState(currentSettings, mInputLogic.mLastSelectionStart,
|
||||||
|
mInputLogic.mLastSelectionEnd);
|
||||||
}
|
}
|
||||||
// isComposingWord() may have changed since we stored wasComposing
|
// isComposingWord() may have changed since we stored wasComposing
|
||||||
if (mInputLogic.mWordComposer.isComposingWord()) {
|
if (mInputLogic.mWordComposer.isComposingWord()) {
|
||||||
|
@ -2227,7 +2024,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shouldAvoidSendingCode) {
|
if (!shouldAvoidSendingCode) {
|
||||||
sendKeyCodePoint(primaryCode);
|
mInputLogic.sendKeyCodePoint(primaryCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Constants.CODE_SPACE == primaryCode) {
|
if (Constants.CODE_SPACE == primaryCode) {
|
||||||
|
@ -2272,12 +2069,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
return didAutoCorrect;
|
return didAutoCorrect;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CharSequence getTextWithUnderline(final String text) {
|
|
||||||
return mInputLogic.mIsAutoCorrectionIndicatorOn
|
|
||||||
? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(this, text)
|
|
||||||
: text;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleClose() {
|
private void handleClose() {
|
||||||
// TODO: Verify that words are logged properly when IME is closed.
|
// TODO: Verify that words are logged properly when IME is closed.
|
||||||
commitTyped(LastComposedWord.NOT_A_SEPARATOR);
|
commitTyped(LastComposedWord.NOT_A_SEPARATOR);
|
||||||
|
@ -2311,12 +2102,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
return currentSettings.isSuggestionsRequested(mDisplayOrientation);
|
return currentSettings.isSuggestionsRequested(mDisplayOrientation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearSuggestionStrip() {
|
// TODO[IL]: Define a clear interface for this
|
||||||
|
public void clearSuggestionStrip() {
|
||||||
setSuggestedWords(SuggestedWords.EMPTY, false);
|
setSuggestedWords(SuggestedWords.EMPTY, false);
|
||||||
setAutoCorrectionIndicator(false);
|
setAutoCorrectionIndicator(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSuggestedWords(final SuggestedWords words, final boolean isAutoCorrection) {
|
// TODO[IL]: Define a clear interface for this
|
||||||
|
public void setSuggestedWords(final SuggestedWords words, final boolean isAutoCorrection) {
|
||||||
mInputLogic.mSuggestedWords = words;
|
mInputLogic.mSuggestedWords = words;
|
||||||
if (mSuggestionStripView != null) {
|
if (mSuggestionStripView != null) {
|
||||||
mSuggestionStripView.setSuggestions(words);
|
mSuggestionStripView.setSuggestions(words);
|
||||||
|
@ -2330,7 +2123,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
&& mInputLogic.mWordComposer.isComposingWord()) {
|
&& mInputLogic.mWordComposer.isComposingWord()) {
|
||||||
mInputLogic.mIsAutoCorrectionIndicatorOn = newAutoCorrectionIndicator;
|
mInputLogic.mIsAutoCorrectionIndicatorOn = newAutoCorrectionIndicator;
|
||||||
final CharSequence textWithUnderline =
|
final CharSequence textWithUnderline =
|
||||||
getTextWithUnderline(mInputLogic.mWordComposer.getTypedWord());
|
mInputLogic.getTextWithUnderline(mInputLogic.mWordComposer.getTypedWord());
|
||||||
// TODO: when called from an updateSuggestionStrip() call that results from a posted
|
// TODO: when called from an updateSuggestionStrip() call that results from a posted
|
||||||
// message, this is called outside any batch edit. Potentially, this may result in some
|
// message, this is called outside any batch edit. Potentially, this may result in some
|
||||||
// janky flickering of the screen, although the display speed makes it unlikely in
|
// janky flickering of the screen, although the display speed makes it unlikely in
|
||||||
|
@ -2604,7 +2397,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
mSuggestionStripView.clear();
|
mSuggestionStripView.clear();
|
||||||
}
|
}
|
||||||
mKeyboardSwitcher.updateShiftState();
|
mKeyboardSwitcher.updateShiftState();
|
||||||
resetComposingState(true /* alsoResetLastComposedWord */);
|
mInputLogic.resetComposingState(true /* alsoResetLastComposedWord */);
|
||||||
final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index];
|
final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index];
|
||||||
mInputLogic.mConnection.commitCompletion(completionInfo);
|
mInputLogic.mConnection.commitCompletion(completionInfo);
|
||||||
mInputLogic.mConnection.endBatchEdit();
|
mInputLogic.mConnection.endBatchEdit();
|
||||||
|
@ -2848,7 +2641,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
* Check if the cursor is actually at the end of a word. If so, restart suggestions on this
|
* Check if the cursor is actually at the end of a word. If so, restart suggestions on this
|
||||||
* word, else do nothing.
|
* word, else do nothing.
|
||||||
*/
|
*/
|
||||||
private void restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() {
|
// TODO[IL]: Move this to InputLogic and make it private.
|
||||||
|
public void restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() {
|
||||||
final CharSequence word =
|
final CharSequence word =
|
||||||
mInputLogic.mConnection.getWordBeforeCursorIfAtEndOfWord(mSettings.getCurrent());
|
mInputLogic.mConnection.getWordBeforeCursorIfAtEndOfWord(mSettings.getCurrent());
|
||||||
if (null != word) {
|
if (null != word) {
|
||||||
|
@ -2900,7 +2694,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
if (tryResumeSuggestions) mHandler.postResumeSuggestions();
|
if (tryResumeSuggestions) mHandler.postResumeSuggestions();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void revertCommit() {
|
// TODO[IL]: Move this to InputLogic and make it private again.
|
||||||
|
public void revertCommit() {
|
||||||
final String previousWord = mInputLogic.mLastComposedWord.mPrevWord;
|
final String previousWord = mInputLogic.mLastComposedWord.mPrevWord;
|
||||||
final String originallyTypedWord = mInputLogic.mLastComposedWord.mTypedWord;
|
final String originallyTypedWord = mInputLogic.mLastComposedWord.mTypedWord;
|
||||||
final String committedWord = mInputLogic.mLastComposedWord.mCommittedWord;
|
final String committedWord = mInputLogic.mLastComposedWord.mCommittedWord;
|
||||||
|
@ -2967,7 +2762,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||||
ResearchLogger.latinIME_promotePhantomSpace();
|
ResearchLogger.latinIME_promotePhantomSpace();
|
||||||
}
|
}
|
||||||
sendKeyCodePoint(Constants.CODE_SPACE);
|
mInputLogic.sendKeyCodePoint(Constants.CODE_SPACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,12 @@
|
||||||
package com.android.inputmethod.latin.inputlogic;
|
package com.android.inputmethod.latin.inputlogic;
|
||||||
|
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.KeyCharacterMap;
|
||||||
|
import android.view.KeyEvent;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
|
||||||
|
import com.android.inputmethod.compat.SuggestionSpanUtils;
|
||||||
import com.android.inputmethod.event.EventInterpreter;
|
import com.android.inputmethod.event.EventInterpreter;
|
||||||
import com.android.inputmethod.keyboard.Keyboard;
|
import com.android.inputmethod.keyboard.Keyboard;
|
||||||
import com.android.inputmethod.keyboard.KeyboardSwitcher;
|
import com.android.inputmethod.keyboard.KeyboardSwitcher;
|
||||||
|
@ -32,9 +36,13 @@ import com.android.inputmethod.latin.Suggest;
|
||||||
import com.android.inputmethod.latin.SuggestedWords;
|
import com.android.inputmethod.latin.SuggestedWords;
|
||||||
import com.android.inputmethod.latin.WordComposer;
|
import com.android.inputmethod.latin.WordComposer;
|
||||||
import com.android.inputmethod.latin.define.ProductionFlag;
|
import com.android.inputmethod.latin.define.ProductionFlag;
|
||||||
|
import com.android.inputmethod.latin.settings.Settings;
|
||||||
|
import com.android.inputmethod.latin.settings.SettingsValues;
|
||||||
import com.android.inputmethod.latin.utils.CollectionUtils;
|
import com.android.inputmethod.latin.utils.CollectionUtils;
|
||||||
import com.android.inputmethod.latin.utils.InputTypeUtils;
|
import com.android.inputmethod.latin.utils.InputTypeUtils;
|
||||||
|
import com.android.inputmethod.latin.utils.LatinImeLoggerUtils;
|
||||||
import com.android.inputmethod.latin.utils.RecapitalizeStatus;
|
import com.android.inputmethod.latin.utils.RecapitalizeStatus;
|
||||||
|
import com.android.inputmethod.latin.utils.StringUtils;
|
||||||
import com.android.inputmethod.research.ResearchLogger;
|
import com.android.inputmethod.research.ResearchLogger;
|
||||||
|
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
@ -43,6 +51,8 @@ import java.util.TreeSet;
|
||||||
* This class manages the input logic.
|
* This class manages the input logic.
|
||||||
*/
|
*/
|
||||||
public final class InputLogic {
|
public final class InputLogic {
|
||||||
|
private static final String TAG = InputLogic.class.getSimpleName();
|
||||||
|
|
||||||
// TODO : Remove this member when we can.
|
// TODO : Remove this member when we can.
|
||||||
private final LatinIME mLatinIME;
|
private final LatinIME mLatinIME;
|
||||||
|
|
||||||
|
@ -84,7 +94,9 @@ public final class InputLogic {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startInput(final boolean restarting) {
|
public void startInput(final boolean restarting) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finishInput() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCodeInput(final int primaryCode, final int x, final int y,
|
public void onCodeInput(final int primaryCode, final int x, final int y,
|
||||||
|
@ -94,6 +106,7 @@ public final class InputLogic {
|
||||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||||
ResearchLogger.latinIME_onCodeInput(primaryCode, x, y);
|
ResearchLogger.latinIME_onCodeInput(primaryCode, x, y);
|
||||||
}
|
}
|
||||||
|
final SettingsValues settingsValues = Settings.getInstance().getCurrent();
|
||||||
final long when = SystemClock.uptimeMillis();
|
final long when = SystemClock.uptimeMillis();
|
||||||
if (primaryCode != Constants.CODE_DELETE
|
if (primaryCode != Constants.CODE_DELETE
|
||||||
|| when > mLastKeyTime + Constants.LONG_PRESS_MILLISECONDS) {
|
|| when > mLastKeyTime + Constants.LONG_PRESS_MILLISECONDS) {
|
||||||
|
@ -121,7 +134,7 @@ public final class InputLogic {
|
||||||
switch (primaryCode) {
|
switch (primaryCode) {
|
||||||
case Constants.CODE_DELETE:
|
case Constants.CODE_DELETE:
|
||||||
mSpaceState = SpaceState.NONE;
|
mSpaceState = SpaceState.NONE;
|
||||||
handleBackspace(spaceState);
|
handleBackspace(settingsValues, spaceState, handler, keyboardSwitcher);
|
||||||
LatinImeLogger.logOnDelete(x, y);
|
LatinImeLogger.logOnDelete(x, y);
|
||||||
break;
|
break;
|
||||||
case Constants.CODE_SHIFT:
|
case Constants.CODE_SHIFT:
|
||||||
|
@ -224,10 +237,151 @@ public final class InputLogic {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a press on the backspace key.
|
* Handle a press on the backspace key.
|
||||||
|
* @param settingsValues The current settings values.
|
||||||
* @param spaceState The space state at start of this batch edit.
|
* @param spaceState The space state at start of this batch edit.
|
||||||
*/
|
*/
|
||||||
private void handleBackspace(final int spaceState) {
|
private void handleBackspace(final SettingsValues settingsValues, final int spaceState,
|
||||||
mLatinIME.handleBackspace(spaceState);
|
// TODO: remove these arguments
|
||||||
|
final LatinIME.UIHandler handler, final KeyboardSwitcher keyboardSwitcher) {
|
||||||
|
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.
|
||||||
|
handler.postUpdateShiftState();
|
||||||
|
|
||||||
|
if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
|
||||||
|
// If we are in the middle of a recorrection, we need to commit the recorrection
|
||||||
|
// first so that we can remove the character at the current cursor position.
|
||||||
|
resetEntireInputState(settingsValues, mLastSelectionStart, mLastSelectionEnd);
|
||||||
|
// When we exit this if-clause, mWordComposer.isComposingWord() will return false.
|
||||||
|
}
|
||||||
|
if (mWordComposer.isComposingWord()) {
|
||||||
|
if (mWordComposer.isBatchMode()) {
|
||||||
|
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||||
|
final String word = mWordComposer.getTypedWord();
|
||||||
|
ResearchLogger.latinIME_handleBackspace_batch(word, 1);
|
||||||
|
}
|
||||||
|
final String rejectedSuggestion = mWordComposer.getTypedWord();
|
||||||
|
mWordComposer.reset();
|
||||||
|
mWordComposer.setRejectedBatchModeSuggestion(rejectedSuggestion);
|
||||||
|
} else {
|
||||||
|
mWordComposer.deleteLast();
|
||||||
|
}
|
||||||
|
mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
|
||||||
|
handler.postUpdateSuggestionStrip();
|
||||||
|
if (!mWordComposer.isComposingWord()) {
|
||||||
|
// If we just removed the last character, auto-caps mode may have changed so we
|
||||||
|
// need to re-evaluate.
|
||||||
|
keyboardSwitcher.updateShiftState();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (mLastComposedWord.canRevertCommit()) {
|
||||||
|
if (settingsValues.mIsInternal) {
|
||||||
|
LatinImeLoggerUtils.onAutoCorrectionCancellation();
|
||||||
|
}
|
||||||
|
mLatinIME.revertCommit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mEnteredText != null && mConnection.sameAsTextBeforeCursor(mEnteredText)) {
|
||||||
|
// Cancel multi-character input: remove the text we just entered.
|
||||||
|
// This is triggered on backspace after a key that inputs multiple characters,
|
||||||
|
// like the smiley key or the .com key.
|
||||||
|
mConnection.deleteSurroundingText(mEnteredText.length(), 0);
|
||||||
|
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||||
|
ResearchLogger.latinIME_handleBackspace_cancelTextInput(mEnteredText);
|
||||||
|
}
|
||||||
|
mEnteredText = null;
|
||||||
|
// If we have mEnteredText, then we know that mHasUncommittedTypedChars == false.
|
||||||
|
// In addition we know that spaceState is false, and that we should not be
|
||||||
|
// reverting any autocorrect at this point. So we can safely return.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (SpaceState.DOUBLE == spaceState) {
|
||||||
|
handler.cancelDoubleSpacePeriodTimer();
|
||||||
|
if (mConnection.revertDoubleSpacePeriod()) {
|
||||||
|
// No need to reset mSpaceState, it has already be done (that's why we
|
||||||
|
// receive it as a parameter)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (SpaceState.SWAP_PUNCTUATION == spaceState) {
|
||||||
|
if (mConnection.revertSwapPunctuation()) {
|
||||||
|
// Likewise
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No cancelling of commit/double space/swap: we have a regular backspace.
|
||||||
|
// We should backspace one char and restart suggestion if at the end of a word.
|
||||||
|
if (mLastSelectionStart != mLastSelectionEnd) {
|
||||||
|
// If there is a selection, remove it.
|
||||||
|
final int numCharsDeleted = mLastSelectionEnd - mLastSelectionStart;
|
||||||
|
mConnection.setSelection(mLastSelectionEnd, mLastSelectionEnd);
|
||||||
|
// Reset mLastSelectionEnd to mLastSelectionStart. This is what is supposed to
|
||||||
|
// happen, and if it's wrong, the next call to onUpdateSelection will correct it,
|
||||||
|
// but we want to set it right away to avoid it being used with the wrong values
|
||||||
|
// later (typically, in a subsequent press on backspace).
|
||||||
|
mLastSelectionEnd = mLastSelectionStart;
|
||||||
|
mConnection.deleteSurroundingText(numCharsDeleted, 0);
|
||||||
|
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||||
|
ResearchLogger.latinIME_handleBackspace(numCharsDeleted,
|
||||||
|
false /* shouldUncommitLogUnit */);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// There is no selection, just delete one character.
|
||||||
|
if (NOT_A_CURSOR_POSITION == mLastSelectionEnd) {
|
||||||
|
// This should never happen.
|
||||||
|
Log.e(TAG, "Backspace when we don't know the selection position");
|
||||||
|
}
|
||||||
|
if (mLatinIME.mAppWorkAroundsUtils.isBeforeJellyBean() ||
|
||||||
|
settingsValues.mInputAttributes.isTypeNull()) {
|
||||||
|
// There are two possible reasons to send a key event: either the field has
|
||||||
|
// type TYPE_NULL, in which case the keyboard should send events, or we are
|
||||||
|
// running in backward compatibility mode. Before Jelly bean, the keyboard
|
||||||
|
// would simulate a hardware keyboard event on pressing enter or delete. This
|
||||||
|
// is bad for many reasons (there are race conditions with commits) but some
|
||||||
|
// applications are relying on this behavior so we continue to support it for
|
||||||
|
// older apps, so we retain this behavior if the app has target SDK < JellyBean.
|
||||||
|
sendDownUpKeyEvent(KeyEvent.KEYCODE_DEL);
|
||||||
|
if (mDeleteCount > Constants.DELETE_ACCELERATE_AT) {
|
||||||
|
sendDownUpKeyEvent(KeyEvent.KEYCODE_DEL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor();
|
||||||
|
if (codePointBeforeCursor == Constants.NOT_A_CODE) {
|
||||||
|
// Nothing to delete before the cursor.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final int lengthToDelete =
|
||||||
|
Character.isSupplementaryCodePoint(codePointBeforeCursor) ? 2 : 1;
|
||||||
|
mConnection.deleteSurroundingText(lengthToDelete, 0);
|
||||||
|
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||||
|
ResearchLogger.latinIME_handleBackspace(lengthToDelete,
|
||||||
|
true /* shouldUncommitLogUnit */);
|
||||||
|
}
|
||||||
|
if (mDeleteCount > Constants.DELETE_ACCELERATE_AT) {
|
||||||
|
final int codePointBeforeCursorToDeleteAgain =
|
||||||
|
mConnection.getCodePointBeforeCursor();
|
||||||
|
if (codePointBeforeCursorToDeleteAgain != Constants.NOT_A_CODE) {
|
||||||
|
final int lengthToDeleteAgain = Character.isSupplementaryCodePoint(
|
||||||
|
codePointBeforeCursorToDeleteAgain) ? 2 : 1;
|
||||||
|
mConnection.deleteSurroundingText(lengthToDeleteAgain, 0);
|
||||||
|
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||||
|
ResearchLogger.latinIME_handleBackspace(lengthToDeleteAgain,
|
||||||
|
true /* shouldUncommitLogUnit */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: move mDisplayOrientation to CurrentSettings.
|
||||||
|
if (settingsValues.isSuggestionsRequested(mLatinIME.mDisplayOrientation)
|
||||||
|
&& settingsValues.mCurrentLanguageHasSpaces) {
|
||||||
|
mLatinIME.restartSuggestionsOnWordBeforeCursorIfAtEndOfWord();
|
||||||
|
}
|
||||||
|
// We just removed a character. We need to update the auto-caps state.
|
||||||
|
keyboardSwitcher.updateShiftState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -264,4 +418,69 @@ public final class InputLogic {
|
||||||
private void onSettingsKeyPressed() {
|
private void onSettingsKeyPressed() {
|
||||||
mLatinIME.onSettingsKeyPressed();
|
mLatinIME.onSettingsKeyPressed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This will reset the whole input state to the starting state. It will clear
|
||||||
|
// the composing word, reset the last composed word, tell the inputconnection about it.
|
||||||
|
// TODO: remove all references to this in LatinIME and make this private
|
||||||
|
public void resetEntireInputState(final SettingsValues settingsValues,
|
||||||
|
final int newSelStart, final int newSelEnd) {
|
||||||
|
final boolean shouldFinishComposition = mWordComposer.isComposingWord();
|
||||||
|
resetComposingState(true /* alsoResetLastComposedWord */);
|
||||||
|
if (settingsValues.mBigramPredictionEnabled) {
|
||||||
|
mLatinIME.clearSuggestionStrip();
|
||||||
|
} else {
|
||||||
|
mLatinIME.setSuggestedWords(settingsValues.mSuggestPuncList, false);
|
||||||
|
}
|
||||||
|
mConnection.resetCachesUponCursorMoveAndReturnSuccess(newSelStart, newSelEnd,
|
||||||
|
shouldFinishComposition);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove all references to this in LatinIME and make this private.
|
||||||
|
public void resetComposingState(final boolean alsoResetLastComposedWord) {
|
||||||
|
mWordComposer.reset();
|
||||||
|
if (alsoResetLastComposedWord) {
|
||||||
|
mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove all references to this in LatinIME and make this private. Also, shouldn't
|
||||||
|
// this go in some *Utils class instead?
|
||||||
|
public CharSequence getTextWithUnderline(final String text) {
|
||||||
|
return mIsAutoCorrectionIndicatorOn
|
||||||
|
? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(mLatinIME, text)
|
||||||
|
: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendDownUpKeyEvent(final int code) {
|
||||||
|
final long eventTime = SystemClock.uptimeMillis();
|
||||||
|
mConnection.sendKeyEvent(new KeyEvent(eventTime, eventTime,
|
||||||
|
KeyEvent.ACTION_DOWN, code, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
|
||||||
|
KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));
|
||||||
|
mConnection.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime,
|
||||||
|
KeyEvent.ACTION_UP, code, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
|
||||||
|
KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove all references to this in LatinIME and make this private
|
||||||
|
public void sendKeyCodePoint(final int code) {
|
||||||
|
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||||
|
ResearchLogger.latinIME_sendKeyCodePoint(code);
|
||||||
|
}
|
||||||
|
// TODO: Remove this special handling of digit letters.
|
||||||
|
// For backward compatibility. See {@link InputMethodService#sendKeyChar(char)}.
|
||||||
|
if (code >= '0' && code <= '9') {
|
||||||
|
sendDownUpKeyEvent(code - '0' + KeyEvent.KEYCODE_0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Constants.CODE_ENTER == code && mLatinIME.mAppWorkAroundsUtils.isBeforeJellyBean()) {
|
||||||
|
// Backward compatibility mode. Before Jelly bean, the keyboard would simulate
|
||||||
|
// a hardware keyboard event on pressing enter or delete. This is bad for many
|
||||||
|
// reasons (there are race conditions with commits) but some applications are
|
||||||
|
// relying on this behavior so we continue to support it for older apps.
|
||||||
|
sendDownUpKeyEvent(KeyEvent.KEYCODE_ENTER);
|
||||||
|
} else {
|
||||||
|
mConnection.commitText(StringUtils.newSingleCodePointString(code), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue