Fix some bugs in editing feature

- Fixed caching of words - some StringBuilders were being recycled while also being cached. Making copies now.
- Fixed regression in revert - don't reset the word composer after saving the accepted word.
- Removed flicker when cursoring through a word - delay the abortCorrection() until we need to and do the correction
   as an atomic operation.
- Fixed replacing of "selected" words (double-tap to select a word)

Still to do:
- Remove flicker on highlighting a word - may need a framework change
- Don't remove spans on text that's already in the text field - may require a framework change.
- Figure out what to do about the punctuations that share the suggestion strip when in correction mode.
main
Amith Yamasani 2010-07-08 15:41:17 -07:00
parent daf88d35e7
commit b71547f2d0
2 changed files with 23 additions and 18 deletions

View File

@ -49,8 +49,8 @@ import android.view.HapticFeedbackConstants;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewParent;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CompletionInfo;
@ -693,12 +693,14 @@ public class LatinIME extends InputMethodService
// If a word is selected // If a word is selected
if ((candidatesStart == candidatesEnd || newSelStart != oldSelStart) if (isPredictionOn() && mJustRevertedSeparator == null
&& (candidatesStart == candidatesEnd || newSelStart != oldSelStart)
&& (newSelStart < newSelEnd - 1 || (!mPredicting)) && (newSelStart < newSelEnd - 1 || (!mPredicting))
&& !mVoiceInputHighlighted) { && !mVoiceInputHighlighted) {
abortCorrection(false);
if (isCursorTouchingWord() || mLastSelectionStart < mLastSelectionEnd) { if (isCursorTouchingWord() || mLastSelectionStart < mLastSelectionEnd) {
postUpdateOldSuggestions(); postUpdateOldSuggestions();
} else {
abortCorrection(false);
} }
} }
} }
@ -1083,6 +1085,8 @@ public class LatinIME extends InputMethodService
InputConnection ic = getCurrentInputConnection(); InputConnection ic = getCurrentInputConnection();
if (ic == null) return; if (ic == null) return;
ic.beginBatchEdit();
if (mAfterVoiceInput) { if (mAfterVoiceInput) {
// Don't log delete if the user is pressing delete at // Don't log delete if the user is pressing delete at
// the beginning of the text box (hence not deleting anything) // the beginning of the text box (hence not deleting anything)
@ -1115,6 +1119,7 @@ public class LatinIME extends InputMethodService
TextEntryState.backspace(); TextEntryState.backspace();
if (TextEntryState.getState() == TextEntryState.STATE_UNDO_COMMIT) { if (TextEntryState.getState() == TextEntryState.STATE_UNDO_COMMIT) {
revertLastWord(deleteChar); revertLastWord(deleteChar);
ic.endBatchEdit();
return; return;
} else if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { } else if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) {
ic.deleteSurroundingText(mEnteredText.length(), 0); ic.deleteSurroundingText(mEnteredText.length(), 0);
@ -1125,6 +1130,7 @@ public class LatinIME extends InputMethodService
} }
} }
mJustRevertedSeparator = null; mJustRevertedSeparator = null;
ic.endBatchEdit();
} }
private void handleShift() { private void handleShift() {
@ -1277,9 +1283,10 @@ public class LatinIME extends InputMethodService
mWord.reset(); mWord.reset();
return; return;
} }
TypedWordAlternatives entry = new TypedWordAlternatives(result, mWord); // Make a copy of the CharSequence, since it is/could be a mutable CharSequence
// Create a new WordComposer as the old one is being saved for later use final String resultCopy = result.toString();
mWord = new WordComposer(mWord); TypedWordAlternatives entry = new TypedWordAlternatives(resultCopy,
new WordComposer(mWord));
mWordHistory.add(entry); mWordHistory.add(entry);
} }
@ -1648,7 +1655,8 @@ public class LatinIME extends InputMethodService
// Fool the state watcher so that a subsequent backspace will not do a revert // Fool the state watcher so that a subsequent backspace will not do a revert
TextEntryState.typedCharacter((char) KEYCODE_SPACE, true); TextEntryState.typedCharacter((char) KEYCODE_SPACE, true);
if (index == 0 && mCorrectionMode > 0 && !mSuggest.isValidWord(suggestion)) { if (index == 0 && mCorrectionMode > 0 && !mSuggest.isValidWord(suggestion)
&& !mSuggest.isValidWord(suggestion.toString().toLowerCase())) {
mCandidateView.showAddToDictionaryHint(suggestion); mCandidateView.showAddToDictionaryHint(suggestion);
} }
if (ic != null) { if (ic != null) {
@ -1662,7 +1670,7 @@ public class LatinIME extends InputMethodService
InputConnection ic = getCurrentInputConnection(); InputConnection ic = getCurrentInputConnection();
EditingUtil.Range range = new EditingUtil.Range(); EditingUtil.Range range = new EditingUtil.Range();
String wordToBeReplaced = EditingUtil.getWordAtCursor(getCurrentInputConnection(), String wordToBeReplaced = EditingUtil.getWordAtCursor(getCurrentInputConnection(),
mWordSeparators, range).trim(); mWordSeparators, range);
if (!mWordToSuggestions.containsKey(wordToBeReplaced)) { if (!mWordToSuggestions.containsKey(wordToBeReplaced)) {
wordToBeReplaced = wordToBeReplaced.toLowerCase(); wordToBeReplaced = wordToBeReplaced.toLowerCase();
} }
@ -1690,9 +1698,6 @@ public class LatinIME extends InputMethodService
InputConnection ic = getCurrentInputConnection(); InputConnection ic = getCurrentInputConnection();
if (ic != null) { if (ic != null) {
rememberReplacedWord(suggestion); rememberReplacedWord(suggestion);
if (mSuggestionShouldReplaceCurrentWord) {
EditingUtil.deleteWordAtCursor(ic, getWordSeparators());
}
if (!VoiceInput.DELETE_SYMBOL.equals(suggestion)) { if (!VoiceInput.DELETE_SYMBOL.equals(suggestion)) {
ic.commitText(suggestion, 1); ic.commitText(suggestion, 1);
} }
@ -1719,9 +1724,8 @@ public class LatinIME extends InputMethodService
} }
if (!mPredicting && isCursorTouchingWord()) { if (!mPredicting && isCursorTouchingWord()) {
EditingUtil.Range range = new EditingUtil.Range(); EditingUtil.Range range = new EditingUtil.Range();
CharSequence touching = CharSequence touching = EditingUtil.getWordAtCursor(getCurrentInputConnection(),
EditingUtil.getWordAtCursor(getCurrentInputConnection(), mWordSeparators, mWordSeparators, range);
range);
if (touching != null && touching.length() > 1) { if (touching != null && touching.length() > 1) {
if (mWordSeparators.indexOf(touching.charAt(touching.length() - 1)) > 0) { if (mWordSeparators.indexOf(touching.charAt(touching.length() - 1)) > 0) {
touching = touching.toString().substring(0, touching.length() - 1); touching = touching.toString().substring(0, touching.length() - 1);
@ -1782,7 +1786,7 @@ public class LatinIME extends InputMethodService
foundWord); foundWord);
showCorrections(alternatives); showCorrections(alternatives);
if (foundWord != null) { if (foundWord != null) {
mWord = foundWord; mWord = new WordComposer(foundWord);
} else { } else {
mWord.reset(); mWord.reset();
} }
@ -1815,6 +1819,7 @@ public class LatinIME extends InputMethodService
private void underlineWord(CharSequence word, int left, int right) { private void underlineWord(CharSequence word, int left, int right) {
InputConnection ic = getCurrentInputConnection(); InputConnection ic = getCurrentInputConnection();
if (ic == null) return; if (ic == null) return;
ic.finishComposingText();
ic.deleteSurroundingText(left, right); ic.deleteSurroundingText(left, right);
ic.setComposingText(word, 1); ic.setComposingText(word, 1);
ic.setSelection(mLastSelectionStart, mLastSelectionStart); ic.setSelection(mLastSelectionStart, mLastSelectionStart);
@ -1859,7 +1864,6 @@ public class LatinIME extends InputMethodService
if (!mPredicting && length > 0) { if (!mPredicting && length > 0) {
final InputConnection ic = getCurrentInputConnection(); final InputConnection ic = getCurrentInputConnection();
mPredicting = true; mPredicting = true;
ic.beginBatchEdit();
mJustRevertedSeparator = ic.getTextBeforeCursor(1, 0); mJustRevertedSeparator = ic.getTextBeforeCursor(1, 0);
if (deleteChar) ic.deleteSurroundingText(1, 0); if (deleteChar) ic.deleteSurroundingText(1, 0);
int toDelete = mCommittedLength; int toDelete = mCommittedLength;
@ -1871,7 +1875,6 @@ public class LatinIME extends InputMethodService
ic.deleteSurroundingText(toDelete, 0); ic.deleteSurroundingText(toDelete, 0);
ic.setComposingText(mComposing, 1); ic.setComposingText(mComposing, 1);
TextEntryState.backspace(); TextEntryState.backspace();
ic.endBatchEdit();
postUpdateSuggestions(); postUpdateSuggestions();
} else { } else {
sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);

View File

@ -55,7 +55,9 @@ public class WordComposer {
mTypedWord = new StringBuilder(copy.mTypedWord); mTypedWord = new StringBuilder(copy.mTypedWord);
mCapsCount = copy.mCapsCount; mCapsCount = copy.mCapsCount;
mAutoCapitalized = copy.mAutoCapitalized; mAutoCapitalized = copy.mAutoCapitalized;
mIsCapitalized = copy.mIsCapitalized;
} }
/** /**
* Clear out the keys registered so far. * Clear out the keys registered so far.
*/ */