From 1079665c3c017ee024a2ffdaf3488cc8c37f087a Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Tue, 25 Mar 2014 15:57:47 +0900 Subject: [PATCH] [CB14] Implement backspace in the combiner chain Bug: 13622107 Bug: 13406701 Change-Id: I0023b398c4451253f9f717e2bd990b8a054004bc --- .../inputmethod/event/CombinerChain.java | 16 +++++++++- .../com/android/inputmethod/event/Event.java | 2 +- .../android/inputmethod/latin/Suggest.java | 7 ++++- .../inputmethod/latin/WordComposer.java | 29 +++++-------------- .../latin/inputlogic/InputLogic.java | 2 +- .../inputmethod/latin/InputLogicTests.java | 20 +++++++++++++ 6 files changed, 50 insertions(+), 26 deletions(-) diff --git a/java/src/com/android/inputmethod/event/CombinerChain.java b/java/src/com/android/inputmethod/event/CombinerChain.java index 5ca9842c1..8b59dc52a 100644 --- a/java/src/com/android/inputmethod/event/CombinerChain.java +++ b/java/src/com/android/inputmethod/event/CombinerChain.java @@ -17,7 +17,9 @@ package com.android.inputmethod.event; import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.utils.CollectionUtils; import java.util.ArrayList; @@ -84,7 +86,19 @@ public class CombinerChain { } } 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(); for (int i = mCombiners.size() - 1; i >= 0; --i) { diff --git a/java/src/com/android/inputmethod/event/Event.java b/java/src/com/android/inputmethod/event/Event.java index 2bfe0732d..646590948 100644 --- a/java/src/com/android/inputmethod/event/Event.java +++ b/java/src/com/android/inputmethod/event/Event.java @@ -229,9 +229,9 @@ public class Event { switch (mType) { case EVENT_MODE_KEY: case EVENT_NOT_HANDLED: + case EVENT_TOGGLE: return ""; case EVENT_INPUT_KEYPRESS: - case EVENT_TOGGLE: return StringUtils.newSingleCodePointString(mCodePoint); case EVENT_GESTURE: case EVENT_SOFTWARE_GENERATED_STRING: diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index ba64028ca..82dbe3c43 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -18,6 +18,7 @@ package com.android.inputmethod.latin; import android.text.TextUtils; +import com.android.inputmethod.event.Event; import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.define.ProductionFlag; @@ -121,7 +122,11 @@ public final class Suggest { if (trailingSingleQuotesCount > 0) { wordComposerForLookup = new WordComposer(wordComposer); 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 { wordComposerForLookup = wordComposer; diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index a60ca3d41..a955f375b 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -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() { - final int size = size(); - if (size > 0) { - // Note: mTypedWord.length() and mCodes.length differ when there are surrogate pairs - final int stringBuilderLength = mTypedWord.length(); - if (stringBuilderLength < size) { - 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(); - } + public void deleteLast(final Event event) { + mCombinerChain.processEvent(mEvents, event); + mTypedWord.replace(0, mTypedWord.length(), + mCombinerChain.getComposingWordWithCombiningFeedback().toString()); + mEvents.add(event); + refreshSize(); // We may have deleted the last one. if (0 == size()) { mIsFirstCharCapitalized = false; diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index 36b30eabe..fdba0d1f3 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -922,7 +922,7 @@ public final class InputLogic { mWordComposer.reset(); mWordComposer.setRejectedBatchModeSuggestion(rejectedSuggestion); } else { - mWordComposer.deleteLast(); + mWordComposer.deleteLast(inputTransaction.mEvent); } mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); handler.postUpdateSuggestionStrip(); diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java index ab6245635..d4e6ad87a 100644 --- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java +++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java @@ -454,4 +454,24 @@ public class InputLogicTests extends InputTestsBase { assertEquals("predictions after recorrection", "Obama", 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()); + } }