Loading java/src/com/android/inputmethod/latin/RichInputConnection.java +17 −1 Original line number Diff line number Diff line Loading @@ -230,6 +230,9 @@ public final class RichInputConnection { public void finishComposingText() { if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); // TODO: this is not correct! The cursor is not necessarily after the composing text. // In the practice right now this is only called when input ends so it will be reset so // it works, but it's wrong and should be fixed. mCommittedTextBeforeComposingText.append(mComposingText); mComposingText.setLength(0); if (null != mIC) { Loading @@ -244,6 +247,9 @@ public final class RichInputConnection { if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); mCommittedTextBeforeComposingText.append(text); // TODO: the following is exceedingly error-prone. Right now when the cursor is in the // middle of the composing word mComposingText only holds the part of the composing text // that is before the cursor, so this actually works, but it's terribly confusing. Fix this. mExpectedSelStart += text.length() - mComposingText.length(); mExpectedSelEnd = mExpectedSelStart; mComposingText.setLength(0); Loading Loading @@ -347,6 +353,9 @@ public final class RichInputConnection { public void deleteSurroundingText(final int beforeLength, final int afterLength) { if (DEBUG_BATCH_NESTING) checkBatchEdit(); // TODO: the following is incorrect if the cursor is not immediately after the composition. // Right now we never come here in this case because we reset the composing state before we // come here in this case, but we need to fix this. final int remainingChars = mComposingText.length() - beforeLength; if (remainingChars >= 0) { mComposingText.setLength(remainingChars); Loading Loading @@ -447,8 +456,12 @@ public final class RichInputConnection { getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE + (end - start), 0); mCommittedTextBeforeComposingText.setLength(0); if (!TextUtils.isEmpty(textBeforeCursor)) { // The cursor is not necessarily at the end of the composing text, but we have its // position in mExpectedSelStart and mExpectedSelEnd. In this case we want the start // of the text, so we should use mExpectedSelStart. In other words, the composing // text starts (mExpectedSelStart - start) characters before the end of textBeforeCursor final int indexOfStartOfComposingText = Math.max(textBeforeCursor.length() - (end - start), 0); Math.max(textBeforeCursor.length() - (mExpectedSelStart - start), 0); mComposingText.append(textBeforeCursor.subSequence(indexOfStartOfComposingText, textBeforeCursor.length())); mCommittedTextBeforeComposingText.append( Loading Loading @@ -544,6 +557,9 @@ public final class RichInputConnection { final int checkLength = LOOKBACK_CHARACTER_NUM - 1; final String reference = prev.length() <= checkLength ? prev.toString() : prev.subSequence(prev.length() - checkLength, prev.length()).toString(); // TODO: right now the following works because mComposingText holds the part of the // composing text that is before the cursor, but this is very confusing. We should // fix it. final StringBuilder internal = new StringBuilder() .append(mCommittedTextBeforeComposingText).append(mComposingText); if (internal.length() > checkLength) { Loading tests/src/com/android/inputmethod/latin/InputLogicTests.java +37 −0 Original line number Diff line number Diff line Loading @@ -385,4 +385,41 @@ public class InputLogicTests extends InputTestsBase { final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest(); assertEquals("no prediction after period", 0, suggestedWords.size()); } public void testPredictionsAfterRecorrection() { final String PREFIX = "A "; final String WORD_TO_TYPE = "Barack"; final String FIRST_NON_TYPED_SUGGESTION = "Barrack"; final int endOfPrefix = PREFIX.length(); final int endOfWord = endOfPrefix + WORD_TO_TYPE.length(); final int endOfSuggestion = endOfPrefix + FIRST_NON_TYPED_SUGGESTION.length(); final int indexForManualCursor = endOfPrefix + 3; // +3 because it's after "Bar" in "Barack" type(PREFIX); mLatinIME.onUpdateSelection(0, 0, endOfPrefix, endOfPrefix, -1, -1); type(WORD_TO_TYPE); pickSuggestionManually(1, FIRST_NON_TYPED_SUGGESTION); mLatinIME.onUpdateSelection(endOfPrefix, endOfPrefix, endOfSuggestion, endOfSuggestion, -1, -1); runMessages(); type(" "); mLatinIME.onUpdateSelection(endOfSuggestion, endOfSuggestion, endOfSuggestion + 1, endOfSuggestion + 1, -1, -1); sleep(DELAY_TO_WAIT_FOR_PREDICTIONS); runMessages(); // Simulate a manual cursor move mInputConnection.setSelection(indexForManualCursor, indexForManualCursor); mLatinIME.onUpdateSelection(endOfSuggestion + 1, endOfSuggestion + 1, indexForManualCursor, indexForManualCursor, -1, -1); sleep(DELAY_TO_WAIT_FOR_PREDICTIONS); runMessages(); pickSuggestionManually(0, WORD_TO_TYPE); mLatinIME.onUpdateSelection(indexForManualCursor, indexForManualCursor, endOfWord, endOfWord, -1, -1); sleep(DELAY_TO_WAIT_FOR_PREDICTIONS); runMessages(); // Test the first prediction is displayed final SuggestedWords suggestedWords = mLatinIME.getSuggestedWords(); assertEquals("predictions after recorrection", "Obama", suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null); } } Loading
java/src/com/android/inputmethod/latin/RichInputConnection.java +17 −1 Original line number Diff line number Diff line Loading @@ -230,6 +230,9 @@ public final class RichInputConnection { public void finishComposingText() { if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); // TODO: this is not correct! The cursor is not necessarily after the composing text. // In the practice right now this is only called when input ends so it will be reset so // it works, but it's wrong and should be fixed. mCommittedTextBeforeComposingText.append(mComposingText); mComposingText.setLength(0); if (null != mIC) { Loading @@ -244,6 +247,9 @@ public final class RichInputConnection { if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); mCommittedTextBeforeComposingText.append(text); // TODO: the following is exceedingly error-prone. Right now when the cursor is in the // middle of the composing word mComposingText only holds the part of the composing text // that is before the cursor, so this actually works, but it's terribly confusing. Fix this. mExpectedSelStart += text.length() - mComposingText.length(); mExpectedSelEnd = mExpectedSelStart; mComposingText.setLength(0); Loading Loading @@ -347,6 +353,9 @@ public final class RichInputConnection { public void deleteSurroundingText(final int beforeLength, final int afterLength) { if (DEBUG_BATCH_NESTING) checkBatchEdit(); // TODO: the following is incorrect if the cursor is not immediately after the composition. // Right now we never come here in this case because we reset the composing state before we // come here in this case, but we need to fix this. final int remainingChars = mComposingText.length() - beforeLength; if (remainingChars >= 0) { mComposingText.setLength(remainingChars); Loading Loading @@ -447,8 +456,12 @@ public final class RichInputConnection { getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE + (end - start), 0); mCommittedTextBeforeComposingText.setLength(0); if (!TextUtils.isEmpty(textBeforeCursor)) { // The cursor is not necessarily at the end of the composing text, but we have its // position in mExpectedSelStart and mExpectedSelEnd. In this case we want the start // of the text, so we should use mExpectedSelStart. In other words, the composing // text starts (mExpectedSelStart - start) characters before the end of textBeforeCursor final int indexOfStartOfComposingText = Math.max(textBeforeCursor.length() - (end - start), 0); Math.max(textBeforeCursor.length() - (mExpectedSelStart - start), 0); mComposingText.append(textBeforeCursor.subSequence(indexOfStartOfComposingText, textBeforeCursor.length())); mCommittedTextBeforeComposingText.append( Loading Loading @@ -544,6 +557,9 @@ public final class RichInputConnection { final int checkLength = LOOKBACK_CHARACTER_NUM - 1; final String reference = prev.length() <= checkLength ? prev.toString() : prev.subSequence(prev.length() - checkLength, prev.length()).toString(); // TODO: right now the following works because mComposingText holds the part of the // composing text that is before the cursor, but this is very confusing. We should // fix it. final StringBuilder internal = new StringBuilder() .append(mCommittedTextBeforeComposingText).append(mComposingText); if (internal.length() > checkLength) { Loading
tests/src/com/android/inputmethod/latin/InputLogicTests.java +37 −0 Original line number Diff line number Diff line Loading @@ -385,4 +385,41 @@ public class InputLogicTests extends InputTestsBase { final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest(); assertEquals("no prediction after period", 0, suggestedWords.size()); } public void testPredictionsAfterRecorrection() { final String PREFIX = "A "; final String WORD_TO_TYPE = "Barack"; final String FIRST_NON_TYPED_SUGGESTION = "Barrack"; final int endOfPrefix = PREFIX.length(); final int endOfWord = endOfPrefix + WORD_TO_TYPE.length(); final int endOfSuggestion = endOfPrefix + FIRST_NON_TYPED_SUGGESTION.length(); final int indexForManualCursor = endOfPrefix + 3; // +3 because it's after "Bar" in "Barack" type(PREFIX); mLatinIME.onUpdateSelection(0, 0, endOfPrefix, endOfPrefix, -1, -1); type(WORD_TO_TYPE); pickSuggestionManually(1, FIRST_NON_TYPED_SUGGESTION); mLatinIME.onUpdateSelection(endOfPrefix, endOfPrefix, endOfSuggestion, endOfSuggestion, -1, -1); runMessages(); type(" "); mLatinIME.onUpdateSelection(endOfSuggestion, endOfSuggestion, endOfSuggestion + 1, endOfSuggestion + 1, -1, -1); sleep(DELAY_TO_WAIT_FOR_PREDICTIONS); runMessages(); // Simulate a manual cursor move mInputConnection.setSelection(indexForManualCursor, indexForManualCursor); mLatinIME.onUpdateSelection(endOfSuggestion + 1, endOfSuggestion + 1, indexForManualCursor, indexForManualCursor, -1, -1); sleep(DELAY_TO_WAIT_FOR_PREDICTIONS); runMessages(); pickSuggestionManually(0, WORD_TO_TYPE); mLatinIME.onUpdateSelection(indexForManualCursor, indexForManualCursor, endOfWord, endOfWord, -1, -1); sleep(DELAY_TO_WAIT_FOR_PREDICTIONS); runMessages(); // Test the first prediction is displayed final SuggestedWords suggestedWords = mLatinIME.getSuggestedWords(); assertEquals("predictions after recorrection", "Obama", suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null); } }