From e0bad8e988a23553181fb670f8a2589a79f22c40 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Fri, 1 Aug 2014 14:15:33 +0900 Subject: [PATCH] [HW12] Use the consumed status of the Event. Change-Id: I1619f6132f8f71bc1291fd6a5604a5e1e3431ae2 --- .../inputmethod/event/CombinerChain.java | 18 +++++++++++++---- .../inputmethod/event/DeadKeyCombiner.java | 8 +++++++- .../com/android/inputmethod/event/Event.java | 4 ++++ .../inputmethod/latin/WordComposer.java | 3 +++ .../latin/inputlogic/InputLogic.java | 20 +++++++++++++++++-- 5 files changed, 46 insertions(+), 7 deletions(-) diff --git a/java/src/com/android/inputmethod/event/CombinerChain.java b/java/src/com/android/inputmethod/event/CombinerChain.java index f69bf4fd0..2d2731f21 100644 --- a/java/src/com/android/inputmethod/event/CombinerChain.java +++ b/java/src/com/android/inputmethod/event/CombinerChain.java @@ -82,6 +82,13 @@ public class CombinerChain { } } + private void updateStateFeedback() { + mStateFeedback.clear(); + for (int i = mCombiners.size() - 1; i >= 0; --i) { + mStateFeedback.append(mCombiners.get(i).getCombiningStateFeedback()); + } + } + /** * Process an event through the combining chain, and return a processed event to apply. * @param previousEvents the list of previous events in this composition @@ -97,7 +104,13 @@ public class CombinerChain { // A combiner can never return more than one event; it can return several // code points, but they should be encapsulated within one event. event = combiner.processEvent(modifiablePreviousEvents, event); + if (event.isConsumed()) { + // If the event is consumed, then we don't pass it to subsequent combiners: + // they should not see it at all. + break; + } } + updateStateFeedback(); return event; } @@ -121,10 +134,7 @@ public class CombinerChain { } } } - mStateFeedback.clear(); - for (int i = mCombiners.size() - 1; i >= 0; --i) { - mStateFeedback.append(mCombiners.get(i).getCombiningStateFeedback()); - } + updateStateFeedback(); } /** diff --git a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java index d816247d8..4f3f4d25f 100644 --- a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java +++ b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java @@ -36,10 +36,16 @@ public class DeadKeyCombiner implements Combiner { @Nonnull public Event processEvent(final ArrayList previousEvents, final Event event) { if (TextUtils.isEmpty(mDeadSequence)) { + // No dead char is currently being tracked: this is the most common case. if (event.isDead()) { + // The event was a dead key. Start tracking it. mDeadSequence.appendCodePoint(event.mCodePoint); + return Event.createConsumedEvent(event); } - return Event.createConsumedEvent(event); + // Regular keystroke when not keeping track of a dead key. Simply said, there are + // no dead keys at all in the current input, so this combiner has nothing to do and + // simply returns the event as is. The majority of events will go through this path. + return event; } else { // TODO: Allow combining for several dead chars rather than only the first one. // The framework doesn't know how to do this now. diff --git a/java/src/com/android/inputmethod/event/Event.java b/java/src/com/android/inputmethod/event/Event.java index 98c827423..f02f7885a 100644 --- a/java/src/com/android/inputmethod/event/Event.java +++ b/java/src/com/android/inputmethod/event/Event.java @@ -227,6 +227,7 @@ public class Event { * @return an identical event marked as consumed. */ public static Event createConsumedEvent(final Event source) { + // A consumed event should not input any text at all, so we pass the empty string as text. return new Event(source.mEventType, source.mText, source.mCodePoint, source.mKeyCode, source.mX, source.mY, source.mSuggestedWordInfo, source.mFlags | FLAG_CONSUMED, source.mNextEvent); @@ -267,6 +268,9 @@ public class Event { } public CharSequence getTextToCommit() { + if (isConsumed()) { + return ""; // A consumed event should input no text. + } switch (mEventType) { case EVENT_TYPE_MODE_KEY: case EVENT_TYPE_NOT_HANDLED: diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index 3b6904847..32d1fe372 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -184,6 +184,9 @@ public final class WordComposer { @Nonnull public Event processEvent(final Event event) { final Event processedEvent = mCombinerChain.processEvent(mEvents, event); + // The retained state of the combiner chain may have changed while processing the event, + // so we need to update our cache. + refreshTypedWordCache(); mEvents.add(event); return processedEvent; } diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index e2feb7c4d..dee7cd466 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -206,7 +206,7 @@ public final class InputLogic { final int keyboardShiftMode, // TODO: remove this argument final LatinIME.UIHandler handler) { - final String rawText = event.mText.toString(); + final String rawText = event.getTextToCommit().toString(); final InputTransaction inputTransaction = new InputTransaction(settingsValues, event, SystemClock.uptimeMillis(), mSpaceState, getActualCapsMode(settingsValues, keyboardShiftMode)); @@ -416,6 +416,8 @@ public final class InputLogic { mLastKeyTime = inputTransaction.mTimestamp; mConnection.beginBatchEdit(); if (!mWordComposer.isComposingWord()) { + // TODO: is this useful? It doesn't look like it should be done here, but rather after + // a word is committed. mIsAutoCorrectionIndicatorOn = false; } @@ -425,7 +427,21 @@ public final class InputLogic { } boolean didAutoCorrect = false; - if (processedEvent.isFunctionalKeyEvent()) { + if (processedEvent.isConsumed()) { + // A consumed event may have text to commit and an update to the composing state, so + // we evaluate both. With some combiners, it's possible than an event contains both + // and we enter both of the following if clauses. + final CharSequence textToCommit = processedEvent.getTextToCommit(); + if (!TextUtils.isEmpty(textToCommit)) { + mConnection.commitText(textToCommit, 1); + inputTransaction.setDidAffectContents(); + } + if (mWordComposer.isComposingWord()) { + mConnection.setComposingText(mWordComposer.getTypedWord(), 1); + inputTransaction.setDidAffectContents(); + inputTransaction.setRequiresUpdateSuggestions(); + } + } else if (processedEvent.isFunctionalKeyEvent()) { // A special key, like delete, shift, emoji, or the settings key. switch (processedEvent.mKeyCode) { case Constants.CODE_DELETE: