aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com
diff options
context:
space:
mode:
authorJean Chalard <jchalard@google.com>2013-12-19 16:07:24 +0900
committerJean Chalard <jchalard@google.com>2013-12-19 16:46:54 +0900
commit0e82fa273d09f781d88a8d222394c7bcc7827745 (patch)
treece6665fcadfea2889bea1361a21cf821ed6350d4 /java/src/com
parentcddf4f9d781850fb4ffcfd8dfc434aa44c5d9f88 (diff)
downloadlatinime-0e82fa273d09f781d88a8d222394c7bcc7827745.tar.gz
latinime-0e82fa273d09f781d88a8d222394c7bcc7827745.tar.xz
latinime-0e82fa273d09f781d88a8d222394c7bcc7827745.zip
[IL3] Move handleBackspace to InputLogic.
Also move resetEntireInputState, resetComposingState, sendDownUpKeyEvent, sendKeyCodePoint and getTextWithUnderline Bug: 8636060 Change-Id: Ic4c270ac49769ffba41dc3f12d16ac3aa938717f
Diffstat (limited to 'java/src/com')
-rw-r--r--java/src/com/android/inputmethod/latin/Constants.java2
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java269
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java227
3 files changed, 257 insertions, 241 deletions
diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java
index ebbd98ced..51e6efbe7 100644
--- a/java/src/com/android/inputmethod/latin/Constants.java
+++ b/java/src/com/android/inputmethod/latin/Constants.java
@@ -156,6 +156,8 @@ public final class Constants {
// Key events coming any faster than this are long-presses.
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) {
// Detect {@link NOT_A_COORDINATE}, {@link SUGGESTION_STRIP_COORDINATE},
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index bdf4f484a..939131259 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -121,9 +121,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
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 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 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;
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
@@ -160,8 +158,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private boolean mUseOnlyPersonalizationDictionaryForDebug = false;
private boolean mBoostPersonalizationDictionaryForDebug = false;
- // Member variables for remembering the current device orientation.
- private int mDisplayOrientation;
+ // Member variable for remembering the current device orientation.
+ // TODO[IL]: Move this to SettingsValues.
+ public int mDisplayOrientation;
// Object for reacting to adding/removing a dictionary pack.
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
// span, so we should reset our state unconditionally, even if restarting is true.
mInputLogic.mEnteredText = null;
- resetComposingState(true /* alsoResetLastComposedWord */);
+ mInputLogic.resetComposingState(true /* alsoResetLastComposedWord */);
mInputLogic.mDeleteCount = 0;
mInputLogic.mSpaceState = SpaceState.NONE;
mInputLogic.mRecapitalizeStatus.deactivate();
@@ -965,7 +964,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (mInputLogic.mWordComposer.isComposingWord()) {
mInputLogic.mConnection.finishComposingText();
}
- resetComposingState(true /* alsoResetLastComposedWord */);
+ mInputLogic.resetComposingState(true /* alsoResetLastComposedWord */);
// Notify ResearchLogger
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
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
// text, but that is probably too expensive to do, so we decided to leave things
// as is.
- resetEntireInputState(newSelStart, newSelEnd);
+ mInputLogic.resetEntireInputState(mSettings.getCurrent(), newSelStart, newSelEnd);
} else {
// resetEntireInputState calls resetCachesUponCursorMove, but forcing the
// 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);
}
- // 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) {
if (!mInputLogic.mWordComposer.isComposingWord()) return;
final String typedWord = mInputLogic.mWordComposer.getTypedWord();
@@ -1459,38 +1436,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
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}.
@Override
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 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.
- resetEntireInputState(mInputLogic.mLastSelectionStart,
- mInputLogic.mLastSelectionEnd);
+ mInputLogic.resetEntireInputState(settingsValues,
+ mInputLogic.mLastSelectionStart, mInputLogic.mLastSelectionEnd);
} else {
commitTyped(LastComposedWord.NOT_A_SEPARATOR);
}
@@ -1547,7 +1492,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (mInputLogic.mWordComposer.isComposingWord()) {
commitCurrentAutoCorrection(rawText);
} else {
- resetComposingState(true /* alsoResetLastComposedWord */);
+ mInputLogic.resetComposingState(true /* alsoResetLastComposedWord */);
}
mHandler.postUpdateSuggestionStrip();
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS
@@ -1590,8 +1535,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (mInputLogic.mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
// 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.
- resetEntireInputState(mInputLogic.mLastSelectionStart,
- mInputLogic.mLastSelectionEnd);
+ mInputLogic.resetEntireInputState(currentSettingsValues,
+ mInputLogic.mLastSelectionStart, mInputLogic.mLastSelectionEnd);
} else if (wordComposerSize <= 1) {
// 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
@@ -1886,156 +1831,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
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.
*/
@@ -2076,7 +1871,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (mInputLogic.mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
// 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.
- resetEntireInputState(mInputLogic.mLastSelectionStart, mInputLogic.mLastSelectionEnd);
+ mInputLogic.resetEntireInputState(currentSettings, mInputLogic.mLastSelectionStart,
+ mInputLogic.mLastSelectionEnd);
isComposingWord = false;
}
// 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
// it entirely and resume suggestions on the previous word, we'd like to still
// have touch coordinates for it.
- resetComposingState(false /* alsoResetLastComposedWord */);
+ mInputLogic.resetComposingState(false /* alsoResetLastComposedWord */);
}
if (isComposingWord) {
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
@@ -2120,13 +1916,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
getActualCapsMode(),
getNthPreviousWordForSuggestion(currentSettings, 1 /* nthPreviousWord */));
}
- mInputLogic.mConnection.setComposingText(getTextWithUnderline(
+ mInputLogic.mConnection.setComposingText(mInputLogic.getTextWithUnderline(
mInputLogic.mWordComposer.getTypedWord()), 1);
} else {
final boolean swapWeakSpace = maybeStripSpace(primaryCode, spaceState,
Constants.SUGGESTION_STRIP_COORDINATE == x);
- sendKeyCodePoint(primaryCode);
+ mInputLogic.sendKeyCodePoint(primaryCode);
if (swapWeakSpace) {
swapSwapperAndSpace();
@@ -2200,7 +1996,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (mInputLogic.mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
// 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.
- resetEntireInputState(mInputLogic.mLastSelectionStart, mInputLogic.mLastSelectionEnd);
+ mInputLogic.resetEntireInputState(currentSettings, mInputLogic.mLastSelectionStart,
+ mInputLogic.mLastSelectionEnd);
}
// isComposingWord() may have changed since we stored wasComposing
if (mInputLogic.mWordComposer.isComposingWord()) {
@@ -2227,7 +2024,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
if (!shouldAvoidSendingCode) {
- sendKeyCodePoint(primaryCode);
+ mInputLogic.sendKeyCodePoint(primaryCode);
}
if (Constants.CODE_SPACE == primaryCode) {
@@ -2272,12 +2069,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return didAutoCorrect;
}
- private CharSequence getTextWithUnderline(final String text) {
- return mInputLogic.mIsAutoCorrectionIndicatorOn
- ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(this, text)
- : text;
- }
-
private void handleClose() {
// TODO: Verify that words are logged properly when IME is closed.
commitTyped(LastComposedWord.NOT_A_SEPARATOR);
@@ -2311,12 +2102,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return currentSettings.isSuggestionsRequested(mDisplayOrientation);
}
- private void clearSuggestionStrip() {
+ // TODO[IL]: Define a clear interface for this
+ public void clearSuggestionStrip() {
setSuggestedWords(SuggestedWords.EMPTY, 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;
if (mSuggestionStripView != null) {
mSuggestionStripView.setSuggestions(words);
@@ -2330,7 +2123,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
&& mInputLogic.mWordComposer.isComposingWord()) {
mInputLogic.mIsAutoCorrectionIndicatorOn = newAutoCorrectionIndicator;
final CharSequence textWithUnderline =
- getTextWithUnderline(mInputLogic.mWordComposer.getTypedWord());
+ mInputLogic.getTextWithUnderline(mInputLogic.mWordComposer.getTypedWord());
// 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
// 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();
}
mKeyboardSwitcher.updateShiftState();
- resetComposingState(true /* alsoResetLastComposedWord */);
+ mInputLogic.resetComposingState(true /* alsoResetLastComposedWord */);
final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index];
mInputLogic.mConnection.commitCompletion(completionInfo);
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
* word, else do nothing.
*/
- private void restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() {
+ // TODO[IL]: Move this to InputLogic and make it private.
+ public void restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() {
final CharSequence word =
mInputLogic.mConnection.getWordBeforeCursorIfAtEndOfWord(mSettings.getCurrent());
if (null != word) {
@@ -2900,7 +2694,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
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 originallyTypedWord = mInputLogic.mLastComposedWord.mTypedWord;
final String committedWord = mInputLogic.mLastComposedWord.mCommittedWord;
@@ -2967,7 +2762,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_promotePhantomSpace();
}
- sendKeyCodePoint(Constants.CODE_SPACE);
+ mInputLogic.sendKeyCodePoint(Constants.CODE_SPACE);
}
}
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index a61305d51..a78628028 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -17,8 +17,12 @@
package com.android.inputmethod.latin.inputlogic;
import android.os.SystemClock;
+import android.util.Log;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
+import com.android.inputmethod.compat.SuggestionSpanUtils;
import com.android.inputmethod.event.EventInterpreter;
import com.android.inputmethod.keyboard.Keyboard;
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.WordComposer;
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.InputTypeUtils;
+import com.android.inputmethod.latin.utils.LatinImeLoggerUtils;
import com.android.inputmethod.latin.utils.RecapitalizeStatus;
+import com.android.inputmethod.latin.utils.StringUtils;
import com.android.inputmethod.research.ResearchLogger;
import java.util.TreeSet;
@@ -43,6 +51,8 @@ import java.util.TreeSet;
* This class manages the input logic.
*/
public final class InputLogic {
+ private static final String TAG = InputLogic.class.getSimpleName();
+
// TODO : Remove this member when we can.
private final LatinIME mLatinIME;
@@ -84,7 +94,9 @@ public final class InputLogic {
}
public void startInput(final boolean restarting) {
-
+ }
+
+ public void finishInput() {
}
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) {
ResearchLogger.latinIME_onCodeInput(primaryCode, x, y);
}
+ final SettingsValues settingsValues = Settings.getInstance().getCurrent();
final long when = SystemClock.uptimeMillis();
if (primaryCode != Constants.CODE_DELETE
|| when > mLastKeyTime + Constants.LONG_PRESS_MILLISECONDS) {
@@ -121,7 +134,7 @@ public final class InputLogic {
switch (primaryCode) {
case Constants.CODE_DELETE:
mSpaceState = SpaceState.NONE;
- handleBackspace(spaceState);
+ handleBackspace(settingsValues, spaceState, handler, keyboardSwitcher);
LatinImeLogger.logOnDelete(x, y);
break;
case Constants.CODE_SHIFT:
@@ -224,10 +237,151 @@ public final class InputLogic {
/**
* Handle a press on the backspace key.
+ * @param settingsValues The current settings values.
* @param spaceState The space state at start of this batch edit.
*/
- private void handleBackspace(final int spaceState) {
- mLatinIME.handleBackspace(spaceState);
+ private void handleBackspace(final SettingsValues settingsValues, final int 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() {
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);
+ }
+ }
}