aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/LatinIME.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin/LatinIME.java')
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java180
1 files changed, 109 insertions, 71 deletions
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index ccdbd0d4d..608bb3cea 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -99,6 +99,7 @@ import com.android.inputmethod.latin.utils.JniUtils;
import com.android.inputmethod.latin.utils.LatinImeLoggerUtils;
import com.android.inputmethod.latin.utils.RecapitalizeStatus;
import com.android.inputmethod.latin.utils.StaticInnerHandlerWrapper;
+import com.android.inputmethod.latin.utils.StringUtils;
import com.android.inputmethod.latin.utils.TargetPackageInfoGetterTask;
import com.android.inputmethod.latin.utils.TextRange;
import com.android.inputmethod.latin.utils.UserHistoryForgettingCurveUtils;
@@ -1261,9 +1262,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final boolean needsInputViewShown) {
// TODO: Modify this if we support suggestions with hard keyboard
if (onEvaluateInputViewShown() && mSuggestionStripView != null) {
- final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
- final boolean inputViewShown = (mainKeyboardView != null)
- ? mainKeyboardView.isShown() : false;
+ final boolean inputViewShown = mKeyboardSwitcher.isShowingMainKeyboardOrEmojiPalettes();
final boolean shouldShowSuggestions = shown
&& (needsInputViewShown ? inputViewShown : true);
if (isFullscreenMode()) {
@@ -1329,7 +1328,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (visibleKeyboardView.isShown()) {
// Note that the height of Emoji layout is the same as the height of the main keyboard
// and the suggestion strip
- if (mKeyboardSwitcher.isShowingEmojiKeyboard()
+ if (mKeyboardSwitcher.isShowingEmojiPalettes()
|| mSuggestionStripView.getVisibility() == View.VISIBLE) {
visibleTopY -= suggestionsHeight;
}
@@ -1588,8 +1587,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// relying on this behavior so we continue to support it for older apps.
sendDownUpKeyEvent(KeyEvent.KEYCODE_ENTER);
} else {
- final String text = new String(new int[] { code }, 0, 1);
- mConnection.commitText(text, text.length());
+ mConnection.commitText(StringUtils.newSingleCodePointString(code), 1);
}
}
@@ -1624,8 +1622,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
case Constants.CODE_DELETE:
mSpaceState = SPACE_STATE_NONE;
handleBackspace(spaceState);
- mDeleteCount++;
- mExpectingUpdateSelection = true;
LatinImeLogger.logOnDelete(x, y);
break;
case Constants.CODE_SHIFT:
@@ -1712,7 +1708,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mSpaceState = SPACE_STATE_NONE;
final boolean didAutoCorrect;
final SettingsValues settingsValues = mSettings.getCurrent();
- if (settingsValues.isWordSeparator(primaryCode)) {
+ if (settingsValues.isWordSeparator(primaryCode)
+ || Character.getType(primaryCode) == Character.OTHER_SYMBOL) {
didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState);
} else {
didAutoCorrect = false;
@@ -1838,12 +1835,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public boolean handleMessage(final Message msg) {
+ // TODO: straighten message passing - we don't need two kinds of messages calling
+ // each other.
switch (msg.what) {
case MSG_UPDATE_GESTURE_PREVIEW_AND_SUGGESTION_STRIP:
- updateBatchInput((InputPointers)msg.obj);
+ updateBatchInput((InputPointers)msg.obj, msg.arg2 /* sequenceNumber */);
break;
case MSG_GET_SUGGESTED_WORDS:
- mLatinIme.getSuggestedWords(msg.arg1, (OnGetSuggestedWordsCallback) msg.obj);
+ mLatinIme.getSuggestedWords(msg.arg1 /* sessionId */,
+ msg.arg2 /* sequenceNumber */, (OnGetSuggestedWordsCallback) msg.obj);
break;
}
return true;
@@ -1860,14 +1860,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
// Run in the Handler thread.
- private void updateBatchInput(final InputPointers batchPointers) {
+ private void updateBatchInput(final InputPointers batchPointers, final int sequenceNumber) {
synchronized (mLock) {
if (!mInBatchInput) {
// Batch input has ended or canceled while the message was being delivered.
return;
}
- getSuggestedWordsGestureLocked(batchPointers, new OnGetSuggestedWordsCallback() {
+ getSuggestedWordsGestureLocked(batchPointers, sequenceNumber,
+ new OnGetSuggestedWordsCallback() {
@Override
public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
mLatinIme.mHandler.showGesturePreviewAndSuggestionStrip(
@@ -1878,13 +1879,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
// Run in the UI thread.
- public void onUpdateBatchInput(final InputPointers batchPointers) {
+ public void onUpdateBatchInput(final InputPointers batchPointers,
+ final int sequenceNumber) {
if (mHandler.hasMessages(MSG_UPDATE_GESTURE_PREVIEW_AND_SUGGESTION_STRIP)) {
return;
}
- mHandler.obtainMessage(
- MSG_UPDATE_GESTURE_PREVIEW_AND_SUGGESTION_STRIP, batchPointers)
- .sendToTarget();
+ mHandler.obtainMessage(MSG_UPDATE_GESTURE_PREVIEW_AND_SUGGESTION_STRIP, 0 /* arg1 */,
+ sequenceNumber /* arg2 */, batchPointers /* obj */).sendToTarget();
}
public void onCancelBatchInput() {
@@ -1898,7 +1899,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Run in the UI thread.
public void onEndBatchInput(final InputPointers batchPointers) {
synchronized(mLock) {
- getSuggestedWordsGestureLocked(batchPointers, new OnGetSuggestedWordsCallback() {
+ getSuggestedWordsGestureLocked(batchPointers, SuggestedWords.NOT_A_SEQUENCE_NUMBER,
+ new OnGetSuggestedWordsCallback() {
@Override
public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
mInBatchInput = false;
@@ -1913,10 +1915,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// {@link LatinIME#getSuggestedWords(int)} method calls with same session id have to
// be synchronized.
private void getSuggestedWordsGestureLocked(final InputPointers batchPointers,
- final OnGetSuggestedWordsCallback callback) {
+ final int sequenceNumber, final OnGetSuggestedWordsCallback callback) {
mLatinIme.mWordComposer.setBatchInputPointers(batchPointers);
mLatinIme.getSuggestedWordsOrOlderSuggestionsAsync(Suggest.SESSION_GESTURE,
- new OnGetSuggestedWordsCallback() {
+ sequenceNumber, new OnGetSuggestedWordsCallback() {
@Override
public void onGetSuggestedWords(SuggestedWords suggestedWords) {
final int suggestionCount = suggestedWords.size();
@@ -1931,9 +1933,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
});
}
- public void getSuggestedWords(final int sessionId,
+ public void getSuggestedWords(final int sessionId, final int sequenceNumber,
final OnGetSuggestedWordsCallback callback) {
- mHandler.obtainMessage(MSG_GET_SUGGESTED_WORDS, sessionId, 0, callback).sendToTarget();
+ mHandler.obtainMessage(MSG_GET_SUGGESTED_WORDS, sessionId, sequenceNumber, callback)
+ .sendToTarget();
}
private void onDestroy() {
@@ -1954,11 +1957,28 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
+ /* The sequence number member is only used in onUpdateBatchInput. It is increased each time
+ * auto-commit happens. The reason we need this is, when auto-commit happens we trim the
+ * input pointers that are held in a singleton, and to know how much to trim we rely on the
+ * results of the suggestion process that is held in mSuggestedWords.
+ * However, the suggestion process is asynchronous, and sometimes we may enter the
+ * onUpdateBatchInput method twice without having recomputed suggestions yet, or having
+ * received new suggestions generated from not-yet-trimmed input pointers. In this case, the
+ * mIndexOfTouchPointOfSecondWords member will be out of date, and we must not use it lest we
+ * remove an unrelated number of pointers (possibly even more than are left in the input
+ * pointers, leading to a crash).
+ * To avoid that, we increase the sequence number each time we auto-commit and trim the
+ * input pointers, and we do not use any suggested words that have been generated with an
+ * earlier sequence number.
+ */
+ private int mAutoCommitSequenceNumber = 1;
@Override
public void onUpdateBatchInput(final InputPointers batchPointers) {
if (mSettings.getCurrent().mPhraseGestureEnabled) {
final SuggestedWordInfo candidate = mSuggestedWords.getAutoCommitCandidate();
- if (null != candidate) {
+ // If these suggested words have been generated with out of date input pointers, then
+ // we skip auto-commit (see comments above on the mSequenceNumber member).
+ if (null != candidate && mSuggestedWords.mSequenceNumber >= mAutoCommitSequenceNumber) {
if (candidate.mSourceDict.shouldAutoCommit(candidate)) {
final String[] commitParts = candidate.mWord.split(" ", 2);
batchPointers.shift(candidate.mIndexOfTouchPointOfSecondWord);
@@ -1967,10 +1987,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mSpaceState = SPACE_STATE_PHANTOM;
mKeyboardSwitcher.updateShiftState();
mWordComposer.setCapitalizedModeAtStartComposingTime(getActualCapsMode());
+ ++mAutoCommitSequenceNumber;
}
}
}
- mInputUpdater.onUpdateBatchInput(batchPointers);
+ mInputUpdater.onUpdateBatchInput(batchPointers, mAutoCommitSequenceNumber);
}
// This method must run in UI Thread.
@@ -2052,6 +2073,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
private void handleBackspace(final int spaceState) {
+ // We revert these in this method if the deletion doesn't happen.
+ mDeleteCount++;
+ mExpectingUpdateSelection = true;
+
// 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.
@@ -2141,8 +2166,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// This should never happen.
Log.e(TAG, "Backspace when we don't know the selection position");
}
- final int lengthToDelete = Character.isSupplementaryCodePoint(
- mConnection.getCodePointBeforeCursor()) ? 2 : 1;
+ final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor();
+ if (codePointBeforeCursor == Constants.NOT_A_CODE) {
+ // Nothing to delete before the cursor. We have to revert the deletion states
+ // that were updated at the beginning of this method.
+ mDeleteCount--;
+ mExpectingUpdateSelection = false;
+ return;
+ }
+ final int lengthToDelete =
+ Character.isSupplementaryCodePoint(codePointBeforeCursor) ? 2 : 1;
if (mAppWorkAroundsUtils.isBeforeJellyBean() ||
currentSettings.mInputAttributes.isTypeNull()) {
// There are two possible reasons to send a key event: either the field has
@@ -2161,12 +2194,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
true /* shouldUncommitLogUnit */);
}
if (mDeleteCount > DELETE_ACCELERATE_AT) {
- final int lengthToDeleteAgain = Character.isSupplementaryCodePoint(
- mConnection.getCodePointBeforeCursor()) ? 2 : 1;
- mConnection.deleteSurroundingText(lengthToDeleteAgain, 0);
- if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
- ResearchLogger.latinIME_handleBackspace(lengthToDeleteAgain,
- true /* shouldUncommitLogUnit */);
+ 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 */);
+ }
}
}
}
@@ -2336,11 +2373,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (mWordComposer.isComposingWord()) { // May have changed since we stored wasComposing
if (currentSettings.mCorrectionEnabled) {
final String separator = shouldAvoidSendingCode ? LastComposedWord.NOT_A_SEPARATOR
- : new String(new int[] { primaryCode }, 0, 1);
+ : StringUtils.newSingleCodePointString(primaryCode);
commitCurrentAutoCorrection(separator);
didAutoCorrect = true;
} else {
- commitTyped(new String(new int[]{primaryCode}, 0, 1));
+ commitTyped(StringUtils.newSingleCodePointString(primaryCode));
}
}
@@ -2489,7 +2526,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final AsyncResultHolder<SuggestedWords> holder = new AsyncResultHolder<SuggestedWords>();
getSuggestedWordsOrOlderSuggestionsAsync(Suggest.SESSION_TYPING,
- new OnGetSuggestedWordsCallback() {
+ SuggestedWords.NOT_A_SEQUENCE_NUMBER, new OnGetSuggestedWordsCallback() {
@Override
public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
holder.set(suggestedWords);
@@ -2504,7 +2541,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
- private void getSuggestedWords(final int sessionId,
+ private void getSuggestedWords(final int sessionId, final int sequenceNumber,
final OnGetSuggestedWordsCallback callback) {
final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
final Suggest suggest = mSuggest;
@@ -2529,18 +2566,19 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
suggest.getSuggestedWords(mWordComposer, prevWord, keyboard.getProximityInfo(),
currentSettings.mBlockPotentiallyOffensive, currentSettings.mCorrectionEnabled,
- additionalFeaturesOptions, sessionId, callback);
+ additionalFeaturesOptions, sessionId, sequenceNumber, callback);
}
private void getSuggestedWordsOrOlderSuggestionsAsync(final int sessionId,
- final OnGetSuggestedWordsCallback callback) {
- mInputUpdater.getSuggestedWords(sessionId, new OnGetSuggestedWordsCallback() {
- @Override
- public void onGetSuggestedWords(SuggestedWords suggestedWords) {
- callback.onGetSuggestedWords(maybeRetrieveOlderSuggestions(
- mWordComposer.getTypedWord(), suggestedWords));
- }
- });
+ final int sequenceNumber, final OnGetSuggestedWordsCallback callback) {
+ mInputUpdater.getSuggestedWords(sessionId, sequenceNumber,
+ new OnGetSuggestedWordsCallback() {
+ @Override
+ public void onGetSuggestedWords(SuggestedWords suggestedWords) {
+ callback.onGetSuggestedWords(maybeRetrieveOlderSuggestions(
+ mWordComposer.getTypedWord(), suggestedWords));
+ }
+ });
}
private SuggestedWords maybeRetrieveOlderSuggestions(final String typedWord,
@@ -2875,30 +2913,30 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// We come here if there weren't any suggestion spans on this word. We will try to
// compute suggestions for it instead.
mInputUpdater.getSuggestedWords(Suggest.SESSION_TYPING,
- new OnGetSuggestedWordsCallback() {
- @Override
- public void onGetSuggestedWords(
- final SuggestedWords suggestedWordsIncludingTypedWord) {
- final SuggestedWords suggestedWords;
- if (suggestedWordsIncludingTypedWord.size() > 1) {
- // We were able to compute new suggestions for this word.
- // Remove the typed word, since we don't want to display it in this case.
- // The #getSuggestedWordsExcludingTypedWord() method sets willAutoCorrect to
- // false.
- suggestedWords = suggestedWordsIncludingTypedWord
- .getSuggestedWordsExcludingTypedWord();
- } else {
- // No saved suggestions, and we were unable to compute any good one either.
- // Rather than displaying an empty suggestion strip, we'll display the
- // original word alone in the middle.
- // Since there is only one word, willAutoCorrect is false.
- suggestedWords = suggestedWordsIncludingTypedWord;
- }
- // We need to pass typedWord because mWordComposer.mTypedWord may differ from
- // typedWord.
- unsetIsAutoCorrectionIndicatorOnAndCallShowSuggestionStrip(suggestedWords,
- typedWord);
- }});
+ SuggestedWords.NOT_A_SEQUENCE_NUMBER, new OnGetSuggestedWordsCallback() {
+ @Override
+ public void onGetSuggestedWords(
+ final SuggestedWords suggestedWordsIncludingTypedWord) {
+ final SuggestedWords suggestedWords;
+ if (suggestedWordsIncludingTypedWord.size() > 1) {
+ // We were able to compute new suggestions for this word.
+ // Remove the typed word, since we don't want to display it in this
+ // case. The #getSuggestedWordsExcludingTypedWord() method sets
+ // willAutoCorrect to false.
+ suggestedWords = suggestedWordsIncludingTypedWord
+ .getSuggestedWordsExcludingTypedWord();
+ } else {
+ // No saved suggestions, and we were unable to compute any good one
+ // either. Rather than displaying an empty suggestion strip, we'll
+ // display the original word alone in the middle.
+ // Since there is only one word, willAutoCorrect is false.
+ suggestedWords = suggestedWordsIncludingTypedWord;
+ }
+ // We need to pass typedWord because mWordComposer.mTypedWord may
+ // differ from typedWord.
+ unsetIsAutoCorrectionIndicatorOnAndCallShowSuggestionStrip(
+ suggestedWords, typedWord);
+ }});
} else {
// We found suggestion spans in the word. We'll create the SuggestedWords out of
// them, and make willAutoCorrect false.
@@ -2979,8 +3017,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final String originallyTypedWord = mLastComposedWord.mTypedWord;
final String committedWord = mLastComposedWord.mCommittedWord;
final int cancelLength = committedWord.length();
- final int separatorLength = LastComposedWord.getSeparatorLength(
- mLastComposedWord.mSeparatorString);
+ // We want java chars, not codepoints for the following.
+ final int separatorLength = mLastComposedWord.mSeparatorString.length();
// TODO: should we check our saved separator against the actual contents of the text view?
final int deleteLength = cancelLength + separatorLength;
if (DEBUG) {