From 8e38b12e9ccc48bcb18b2eeec4d53d19cf7a29c9 Mon Sep 17 00:00:00 2001
From: Jean Chalard <jchalard@google.com>
Date: Tue, 1 Jul 2014 13:07:47 +0900
Subject: [PATCH] [HW7] Introduce consumed events

Change-Id: I692c35b8e701d5a84500b949884472545b1f424d
---
 .../inputmethod/event/CombinerChain.java      |  2 ++
 .../inputmethod/event/DeadKeyCombiner.java    |  3 +--
 .../com/android/inputmethod/event/Event.java  | 15 ++++++++++++++
 .../inputmethod/event/MyanmarReordering.java  | 20 +++++++++----------
 .../inputmethod/latin/WordComposer.java       |  6 +++---
 5 files changed, 31 insertions(+), 15 deletions(-)

diff --git a/java/src/com/android/inputmethod/event/CombinerChain.java b/java/src/com/android/inputmethod/event/CombinerChain.java
index 8c6b3d949f..8ddc9e7d91 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<Event> previousEvents, final Event newEvent) {
         final ArrayList<Event> 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 bef4d85940..342f499c92 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<Event> 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 d257441e05..98c8274230 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 32919932d3..80c711f4ac 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 2485cf4117..4284884f76 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.
-- 
GitLab