[CB14] Implement backspace in the combiner chain

Bug: 13622107
Bug: 13406701
Change-Id: I0023b398c4451253f9f717e2bd990b8a054004bc
main
Jean Chalard 2014-03-25 15:57:47 +09:00
parent 37b9562fd7
commit 1079665c3c
6 changed files with 50 additions and 26 deletions

View File

@ -17,7 +17,9 @@
package com.android.inputmethod.event; package com.android.inputmethod.event;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.CollectionUtils;
import java.util.ArrayList; import java.util.ArrayList;
@ -84,7 +86,19 @@ public class CombinerChain {
} }
} }
if (null != event) { if (null != event) {
mCombinedText.append(event.getTextToCommit()); // TODO: figure out the generic way of doing this
if (Constants.CODE_DELETE == event.mKeyCode) {
final int length = mCombinedText.length();
if (length > 0) {
final int lastCodePoint = mCombinedText.codePointBefore(length);
mCombinedText.delete(length - Character.charCount(lastCodePoint), length);
}
} else {
final CharSequence textToCommit = event.getTextToCommit();
if (!TextUtils.isEmpty(textToCommit)) {
mCombinedText.append(textToCommit);
}
}
} }
mStateFeedback.clear(); mStateFeedback.clear();
for (int i = mCombiners.size() - 1; i >= 0; --i) { for (int i = mCombiners.size() - 1; i >= 0; --i) {

View File

@ -229,9 +229,9 @@ public class Event {
switch (mType) { switch (mType) {
case EVENT_MODE_KEY: case EVENT_MODE_KEY:
case EVENT_NOT_HANDLED: case EVENT_NOT_HANDLED:
case EVENT_TOGGLE:
return ""; return "";
case EVENT_INPUT_KEYPRESS: case EVENT_INPUT_KEYPRESS:
case EVENT_TOGGLE:
return StringUtils.newSingleCodePointString(mCodePoint); return StringUtils.newSingleCodePointString(mCodePoint);
case EVENT_GESTURE: case EVENT_GESTURE:
case EVENT_SOFTWARE_GENERATED_STRING: case EVENT_SOFTWARE_GENERATED_STRING:

View File

@ -18,6 +18,7 @@ package com.android.inputmethod.latin;
import android.text.TextUtils; import android.text.TextUtils;
import com.android.inputmethod.event.Event;
import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.keyboard.ProximityInfo;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.latin.define.ProductionFlag;
@ -121,7 +122,11 @@ public final class Suggest {
if (trailingSingleQuotesCount > 0) { if (trailingSingleQuotesCount > 0) {
wordComposerForLookup = new WordComposer(wordComposer); wordComposerForLookup = new WordComposer(wordComposer);
for (int i = trailingSingleQuotesCount - 1; i >= 0; --i) { for (int i = trailingSingleQuotesCount - 1; i >= 0; --i) {
wordComposerForLookup.deleteLast(); // TODO: do not create a fake event for this. Ideally the word composer should know
// how to give out the word without trailing quotes and we can remove this entirely
wordComposerForLookup.deleteLast(Event.createSoftwareKeypressEvent(
Event.NOT_A_CODE_POINT, Constants.CODE_DELETE,
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE));
} }
} else { } else {
wordComposerForLookup = wordComposer; wordComposerForLookup = wordComposer;

View File

@ -314,29 +314,14 @@ public final class WordComposer {
} }
/** /**
* Delete the last keystroke as a result of hitting backspace. * Delete the last composing unit as a result of hitting backspace.
*/ */
public void deleteLast() { public void deleteLast(final Event event) {
final int size = size(); mCombinerChain.processEvent(mEvents, event);
if (size > 0) { mTypedWord.replace(0, mTypedWord.length(),
// Note: mTypedWord.length() and mCodes.length differ when there are surrogate pairs mCombinerChain.getComposingWordWithCombiningFeedback().toString());
final int stringBuilderLength = mTypedWord.length(); mEvents.add(event);
if (stringBuilderLength < size) { refreshSize();
throw new RuntimeException(
"In WordComposer: mCodes and mTypedWords have non-matching lengths");
}
final int lastChar = mTypedWord.codePointBefore(stringBuilderLength);
// TODO: with events and composition, this is absolutely not necessarily true.
mEvents.remove(mEvents.size() - 1);
if (Character.isSupplementaryCodePoint(lastChar)) {
mTypedWord.delete(stringBuilderLength - 2, stringBuilderLength);
} else {
mTypedWord.deleteCharAt(stringBuilderLength - 1);
}
if (Character.isUpperCase(lastChar)) mCapsCount--;
if (Character.isDigit(lastChar)) mDigitsCount--;
refreshSize();
}
// We may have deleted the last one. // We may have deleted the last one.
if (0 == size()) { if (0 == size()) {
mIsFirstCharCapitalized = false; mIsFirstCharCapitalized = false;

View File

@ -922,7 +922,7 @@ public final class InputLogic {
mWordComposer.reset(); mWordComposer.reset();
mWordComposer.setRejectedBatchModeSuggestion(rejectedSuggestion); mWordComposer.setRejectedBatchModeSuggestion(rejectedSuggestion);
} else { } else {
mWordComposer.deleteLast(); mWordComposer.deleteLast(inputTransaction.mEvent);
} }
mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
handler.postUpdateSuggestionStrip(); handler.postUpdateSuggestionStrip();

View File

@ -454,4 +454,24 @@ public class InputLogicTests extends InputTestsBase {
assertEquals("predictions after recorrection", "Obama", assertEquals("predictions after recorrection", "Obama",
suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null); suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null);
} }
public void testComposingMultipleBackspace() {
final String WORD_TO_TYPE = "radklro";
final int TIMES_TO_TYPE = 3;
final int TIMES_TO_BACKSPACE = 8;
type(WORD_TO_TYPE);
type(Constants.CODE_DELETE);
type(Constants.CODE_DELETE);
type(Constants.CODE_DELETE);
type(WORD_TO_TYPE);
type(Constants.CODE_DELETE);
type(Constants.CODE_DELETE);
type(WORD_TO_TYPE);
type(Constants.CODE_DELETE);
type(Constants.CODE_DELETE);
type(Constants.CODE_DELETE);
assertEquals("composing with multiple backspace",
WORD_TO_TYPE.length() * TIMES_TO_TYPE - TIMES_TO_BACKSPACE,
mEditText.getText().length());
}
} }