diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 5c91a1077568601d47d707a7adf4a1c14b7d5d79..4cae6bcdbec90123434553d7f32df206d971f892 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -188,32 +188,31 @@ public class BinaryDictionary extends Dictionary {
             char[] outputChars, int[] scores, int[] spaceIndices) {
         if (!isValidDictionary()) return -1;
 
-        final int codesSize = codes.size();
-        // Won't deal with really long words.
-        if (codesSize > MAX_WORD_LENGTH - 1) return -1;
-
         Arrays.fill(mInputCodes, WordComposer.NOT_A_CODE);
-        for (int i = 0; i < codesSize; i++) {
-            mInputCodes[i] = codes.getCodeAt(i);
-        }
         Arrays.fill(outputChars, (char) 0);
         Arrays.fill(scores, 0);
 
+        final InputPointers ips = codes.getInputPointers();
+        final boolean isGesture = codes.isBatchMode();
+        final int codesSize;
+        if (isGesture) {
+            codesSize = ips.getPointerSize();
+        } else {
+            codesSize = codes.size();
+            // Won't deal with really long words.
+            if (codesSize > MAX_WORD_LENGTH - 1) return -1;
+            for (int i = 0; i < codesSize; i++) {
+                mInputCodes[i] = codes.getCodeAt(i);
+            }
+        }
+
         // TODO: toLowerCase in the native code
         final int[] prevWordCodePointArray = (null == prevWordForBigrams)
                 ? null : StringUtils.toCodePointArray(prevWordForBigrams.toString());
 
-        int[] emptyArray = new int[codesSize];
-        Arrays.fill(emptyArray, 0);
-
-        //final int commitPoint = codes.getCommitPoint();
-        //codes.clearCommitPoint();
-
-        final InputPointers ips = codes.getInputPointers();
-
         return getSuggestionsNative(mNativeDict, proximityInfo.getNativeProximityInfo(),
             ips.getXCoordinates(), ips.getYCoordinates(), ips.getTimes(), ips.getPointerIds(),
-            mInputCodes, codesSize, 0 /* unused */, false, prevWordCodePointArray,
+            mInputCodes, codesSize, 0 /* unused */, isGesture, prevWordCodePointArray,
             mUseFullEditDistance, outputChars, scores, spaceIndices);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index c4a7787fab199e9e9367b54d3a8e91d527c7c3e9..31c6000e3db694b2b63a79cca6fd9ad43e625ed3 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -153,12 +153,23 @@ public class Suggest {
         mAutoCorrectionThreshold = threshold;
     }
 
-    // TODO: cleanup dictionaries looking up and suggestions building with SuggestedWords.Builder
     public SuggestedWords getSuggestedWords(
             final WordComposer wordComposer, CharSequence prevWordForBigram,
             final ProximityInfo proximityInfo, final boolean isCorrectionEnabled) {
-        final boolean isPrediction = !wordComposer.isComposingWord();
         LatinImeLogger.onStartSuggestion(prevWordForBigram);
+        if (wordComposer.isBatchMode()) {
+            return getSuggestedWordsForBatchInput(wordComposer, prevWordForBigram, proximityInfo);
+        } else {
+            return getSuggestedWordsForTypingInput(wordComposer, prevWordForBigram, proximityInfo,
+                    isCorrectionEnabled);
+        }
+    }
+
+    // Retrieves suggestions for the typing input.
+    private SuggestedWords getSuggestedWordsForTypingInput(
+            final WordComposer wordComposer, CharSequence prevWordForBigram,
+            final ProximityInfo proximityInfo, final boolean isCorrectionEnabled) {
+        final boolean isPrediction = !wordComposer.isComposingWord();
         final boolean isFirstCharCapitalized =
                 !isPrediction && wordComposer.isFirstCharCapitalized();
         final boolean isAllUpperCase = !isPrediction && wordComposer.isAllUpperCase();
@@ -285,6 +296,37 @@ public class Suggest {
                 isPrediction);
     }
 
+    // Retrieves suggestions for the batch input.
+    private SuggestedWords getSuggestedWordsForBatchInput(
+            final WordComposer wordComposer, CharSequence prevWordForBigram,
+            final ProximityInfo proximityInfo) {
+        final BoundedTreeSet suggestionsSet = new BoundedTreeSet(sSuggestedWordInfoComparator,
+                MAX_SUGGESTIONS);
+
+        // At second character typed, search the unigrams (scores being affected by bigrams)
+        for (final String key : mDictionaries.keySet()) {
+            // Skip UserUnigramDictionary and WhitelistDictionary to lookup
+            if (key.equals(Dictionary.TYPE_USER_HISTORY)
+                    || key.equals(Dictionary.TYPE_WHITELIST)) {
+                continue;
+            }
+            final Dictionary dictionary = mDictionaries.get(key);
+            suggestionsSet.addAll(dictionary.getSuggestions(
+                    wordComposer, prevWordForBigram, proximityInfo));
+        }
+
+        final ArrayList<SuggestedWordInfo> suggestionsContainer =
+                new ArrayList<SuggestedWordInfo>(suggestionsSet);
+
+        SuggestedWordInfo.removeDups(suggestionsContainer);
+        return new SuggestedWords(suggestionsContainer,
+                true /* typedWordValid */,
+                true /* willAutoCorrect */,
+                false /* isPunctuationSuggestions */,
+                false /* isObsoleteSuggestions */,
+                false /* isPrediction */);
+    }
+
     private static ArrayList<SuggestedWordInfo> getSuggestionsInfoListWithDebugInfo(
             final String typedWord, final ArrayList<SuggestedWordInfo> suggestions) {
         final SuggestedWordInfo typedWordInfo = suggestions.get(0);
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index b55c1a546f7185247e1b16d9abb1ed8dd43c9003..46c892afee8f6cc438e1476b0a71c4f1d0e50577 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -37,6 +37,7 @@ public class WordComposer {
     private final StringBuilder mTypedWord;
     private CharSequence mAutoCorrection;
     private boolean mIsResumed;
+    private boolean mIsBatchMode;
 
     // Cache these values for performance
     private int mCapsCount;
@@ -55,6 +56,7 @@ public class WordComposer {
         mAutoCorrection = null;
         mTrailingSingleQuotesCount = 0;
         mIsResumed = false;
+        mIsBatchMode = false;
         refreshSize();
     }
 
@@ -67,6 +69,7 @@ public class WordComposer {
         mAutoCapitalized = source.mAutoCapitalized;
         mTrailingSingleQuotesCount = source.mTrailingSingleQuotesCount;
         mIsResumed = source.mIsResumed;
+        mIsBatchMode = source.mIsBatchMode;
         refreshSize();
     }
 
@@ -80,6 +83,7 @@ public class WordComposer {
         mIsFirstCharCapitalized = false;
         mTrailingSingleQuotesCount = 0;
         mIsResumed = false;
+        mIsBatchMode = false;
         refreshSize();
     }
 
@@ -140,6 +144,12 @@ public class WordComposer {
         mAutoCorrection = null;
     }
 
+    // TODO: We may want to have appendBatchInputPointers() as well.
+    public void setBatchInputPointers(InputPointers batchPointers) {
+        mInputPointers.copy(batchPointers);
+        mIsBatchMode = true;
+    }
+
     /**
      * Internal method to retrieve reasonable proximity info for a character.
      */
@@ -312,4 +322,8 @@ public class WordComposer {
         mAutoCorrection = null; // This will be filled by the next call to updateSuggestion.
         mIsResumed = true;
     }
+
+    public boolean isBatchMode() {
+        return mIsBatchMode;
+    }
 }