diff --git a/java/src/com/android/inputmethod/event/CombinerChain.java b/java/src/com/android/inputmethod/event/CombinerChain.java
index 61bc11b398c96f54859413118acb7874659a077c..8c6b3d949fb0f2893ecbecca7aa1d26c7516b4e2 100644
--- a/java/src/com/android/inputmethod/event/CombinerChain.java
+++ b/java/src/com/android/inputmethod/event/CombinerChain.java
@@ -81,11 +81,11 @@ public class CombinerChain {
     }
 
     /**
-     * Pass a new event through the whole chain.
+     * 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
      */
-    public void processEvent(final ArrayList<Event> previousEvents, final Event newEvent) {
+    public Event processEvent(final ArrayList<Event> previousEvents, final Event newEvent) {
         final ArrayList<Event> modifiablePreviousEvents = new ArrayList<>(previousEvents);
         Event event = newEvent;
         for (final Combiner combiner : mCombiners) {
@@ -97,6 +97,14 @@ public class CombinerChain {
                 break;
             }
         }
+        return event;
+    }
+
+    /**
+     * Apply a processed event.
+     * @param event the event to be applied
+     */
+    public void applyProcessedEvent(final Event event) {
         if (null != event) {
             // TODO: figure out the generic way of doing this
             if (Constants.CODE_DELETE == event.mKeyCode) {
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index cdd7822441f377ae2c5132dc9b551dcaa28668c5..df79584707fa886f5ee3e474c1d5a7565e342987 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -175,20 +175,30 @@ public final class WordComposer {
     }
 
     /**
-     * Process an input event.
+     * Process an event and return an event, and return a processed event to apply.
+     * @param event the unprocessed event.
+     * @return the processed event.
+     */
+    public Event processEvent(final Event event) {
+        final Event processedEvent = mCombinerChain.processEvent(mEvents, event);
+        mEvents.add(event);
+        return processedEvent;
+    }
+
+    /**
+     * Apply a processed input event.
      *
      * All input events should be supported, including software/hardware events, characters as well
      * as deletions, multiple inputs and gestures.
      *
-     * @param event the event to process.
+     * @param event the event to apply.
      */
-    public void processEvent(final Event event) {
+    public void applyProcessedEvent(final Event event) {
         final int primaryCode = event.mCodePoint;
         final int keyX = event.mX;
         final int keyY = event.mY;
         final int newIndex = size();
-        mCombinerChain.processEvent(mEvents, event);
-        mEvents.add(event);
+        mCombinerChain.applyProcessedEvent(event);
         refreshTypedWordCache();
         mCursorPositionWithinWord = mCodePointSize;
         // We may have deleted the last one.
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 74d8799199eee37de4edaaf4536dda48a32f4474..bb2d304a60d951ea857be997ef4cfec30e02e2ed 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -762,7 +762,8 @@ public final class InputLogic {
             resetComposingState(false /* alsoResetLastComposedWord */);
         }
         if (isComposingWord) {
-            mWordComposer.processEvent(inputTransaction.mEvent);
+            final Event processedEvent = mWordComposer.processEvent(inputTransaction.mEvent);
+            mWordComposer.applyProcessedEvent(processedEvent);
             // If it's the first letter, make note of auto-caps state
             if (mWordComposer.isSingleLetter()) {
                 mWordComposer.setCapitalizedModeAtStartComposingTime(inputTransaction.mShiftState);
@@ -933,7 +934,8 @@ public final class InputLogic {
                     mDictionaryFacilitator.removeWordFromPersonalizedDicts(rejectedSuggestion);
                 }
             } else {
-                mWordComposer.processEvent(inputTransaction.mEvent);
+                final Event processedEvent = mWordComposer.processEvent(inputTransaction.mEvent);
+                mWordComposer.applyProcessedEvent(processedEvent);
             }
             if (mWordComposer.isComposingWord()) {
                 mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);