diff --git a/java/src/com/android/inputmethod/event/CombinerChain.java b/java/src/com/android/inputmethod/event/CombinerChain.java index 8c6b3d949..8ddc9e7d9 100644 --- a/java/src/com/android/inputmethod/event/CombinerChain.java +++ b/java/src/com/android/inputmethod/event/CombinerChain.java @@ -84,6 +84,8 @@ public class CombinerChain { * Process an event through the combining chain, and return a processed event to apply. * @param previousEvents the list of previous events in this composition * @param newEvent the new event to process + * @return the processed event. It may be the same event, or a consumed event, or a completely + * new event. However it may never be null. */ public Event processEvent(final ArrayList previousEvents, final Event newEvent) { final ArrayList modifiablePreviousEvents = new ArrayList<>(previousEvents); diff --git a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java index bef4d8594..342f499c9 100644 --- a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java +++ b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java @@ -32,12 +32,11 @@ public class DeadKeyCombiner implements Combiner { @Override public Event processEvent(final ArrayList previousEvents, final Event event) { - if (null == event) return null; // Just in case some combiner is broken if (TextUtils.isEmpty(mDeadSequence)) { if (event.isDead()) { mDeadSequence.appendCodePoint(event.mCodePoint); } - return event; + return Event.createConsumedEvent(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 d257441e0..98c827423 100644 --- a/java/src/com/android/inputmethod/event/Event.java +++ b/java/src/com/android/inputmethod/event/Event.java @@ -67,6 +67,8 @@ public class Event { final private static int FLAG_DEAD = 0x1; // This event is coming from a key repeat, software or hardware. final private static int FLAG_REPEAT = 0x2; + // This event has already been consumed. + final private static int FLAG_CONSUMED = 0x4; final private int mEventType; // The type of event - one of the constants above // The code point associated with the event, if relevant. This is a unicode code point, and @@ -219,6 +221,17 @@ public class Event { null /* next */); } + /** + * Creates an event identical to the passed event, but that has already been consumed. + * @param source the event to copy the properties of. + * @return an identical event marked as consumed. + */ + public static Event createConsumedEvent(final Event source) { + return new Event(source.mEventType, source.mText, source.mCodePoint, source.mKeyCode, + source.mX, source.mY, source.mSuggestedWordInfo, source.mFlags | FLAG_CONSUMED, + source.mNextEvent); + } + public static Event createNotHandledEvent() { return new Event(EVENT_TYPE_NOT_HANDLED, null /* text */, NOT_A_CODE_POINT, NOT_A_KEY_CODE, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, @@ -241,6 +254,8 @@ public class Event { return 0 != (FLAG_REPEAT & mFlags); } + public boolean isConsumed() { return 0 != (FLAG_CONSUMED & mFlags); } + // Returns whether this is a fake key press from the suggestion strip. This happens with // punctuation signs selected from the suggestion strip. public boolean isSuggestionStripPress() { diff --git a/java/src/com/android/inputmethod/event/MyanmarReordering.java b/java/src/com/android/inputmethod/event/MyanmarReordering.java index 32919932d..80c711f4a 100644 --- a/java/src/com/android/inputmethod/event/MyanmarReordering.java +++ b/java/src/com/android/inputmethod/event/MyanmarReordering.java @@ -111,7 +111,7 @@ public class MyanmarReordering implements Combiner { * Clears the currently combining stream of events and returns the resulting software text * event corresponding to the stream. Optionally adds a new event to the cleared stream. * @param newEvent the new event to add to the stream. null if none. - * @return the resulting software text event. Null if none. + * @return the resulting software text event. Never null. */ private Event clearAndGetResultingEvent(final Event newEvent) { final CharSequence combinedText; @@ -124,7 +124,7 @@ public class MyanmarReordering implements Combiner { if (null != newEvent) { mCurrentEvents.add(newEvent); } - return null == combinedText ? null + return null == combinedText ? Event.createConsumedEvent(newEvent) : Event.createSoftwareTextEvent(combinedText, Event.NOT_A_KEY_CODE); } @@ -135,7 +135,7 @@ public class MyanmarReordering implements Combiner { final Event lastEvent = getLastEvent(); if (null == lastEvent) { mCurrentEvents.add(newEvent); - return null; + return Event.createConsumedEvent(newEvent); } else if (isConsonantOrMedial(lastEvent.mCodePoint)) { final Event resultingEvent = clearAndGetResultingEvent(null); mCurrentEvents.add(Event.createSoftwareKeypressEvent(ZERO_WIDTH_NON_JOINER, @@ -151,7 +151,7 @@ public class MyanmarReordering implements Combiner { final Event lastEvent = getLastEvent(); if (null == lastEvent) { mCurrentEvents.add(newEvent); - return null; + return Event.createConsumedEvent(newEvent); } else if (VOWEL_E == lastEvent.mCodePoint) { final int eventSize = mCurrentEvents.size(); if (eventSize >= 2 @@ -162,7 +162,7 @@ public class MyanmarReordering implements Combiner { mCurrentEvents.remove(eventSize - 2); mCurrentEvents.add(newEvent); mCurrentEvents.add(lastEvent); - return null; + return Event.createConsumedEvent(newEvent); } // If there is already a consonant, then we are starting a new syllable. for (int i = eventSize - 2; i >= 0; --i) { @@ -174,7 +174,7 @@ public class MyanmarReordering implements Combiner { mCurrentEvents.remove(eventSize - 1); mCurrentEvents.add(newEvent); mCurrentEvents.add(lastEvent); - return null; + return Event.createConsumedEvent(newEvent); } else { // lastCodePoint is a consonant/medial. But if it's something else it's fine return clearAndGetResultingEvent(newEvent); } @@ -182,7 +182,7 @@ public class MyanmarReordering implements Combiner { final Event lastEvent = getLastEvent(); if (null == lastEvent) { mCurrentEvents.add(newEvent); - return null; + return Event.createConsumedEvent(newEvent); } else if (VOWEL_E == lastEvent.mCodePoint) { final int eventSize = mCurrentEvents.size(); // If there is already a consonant, then we are in the middle of a syllable, and we @@ -198,7 +198,7 @@ public class MyanmarReordering implements Combiner { mCurrentEvents.remove(eventSize - 1); mCurrentEvents.add(newEvent); mCurrentEvents.add(lastEvent); - return null; + return Event.createConsumedEvent(newEvent); } // Otherwise, we just commit everything. return clearAndGetResultingEvent(null); @@ -228,10 +228,10 @@ public class MyanmarReordering implements Combiner { mCurrentEvents.remove(eventSize - 1); } } - return null; + return Event.createConsumedEvent(newEvent); } else if (eventSize > 0) { mCurrentEvents.remove(eventSize - 1); - return null; + return Event.createConsumedEvent(newEvent); } } } diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index df7958470..171d0bba7 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -177,7 +177,7 @@ public final class WordComposer { /** * Process an event and return an event, and return a processed event to apply. * @param event the unprocessed event. - * @return the processed event. + * @return the processed event. Never null, but may be marked as consumed. */ public Event processEvent(final Event event) { final Event processedEvent = mCombinerChain.processEvent(mEvents, event); @@ -191,14 +191,14 @@ public final class WordComposer { * All input events should be supported, including software/hardware events, characters as well * as deletions, multiple inputs and gestures. * - * @param event the event to apply. + * @param event the event to apply. Must not be null. */ public void applyProcessedEvent(final Event event) { + mCombinerChain.applyProcessedEvent(event); final int primaryCode = event.mCodePoint; final int keyX = event.mX; final int keyY = event.mY; final int newIndex = size(); - mCombinerChain.applyProcessedEvent(event); refreshTypedWordCache(); mCursorPositionWithinWord = mCodePointSize; // We may have deleted the last one.