diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 3005920b1cdb3bcf95ecaf27204a1f828782f0c1..06d44680d62b4f9a009328341e84e94ccee164cb 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -174,7 +174,7 @@ public class Keyboard {
         mDefaultHeight = mDefaultWidth;
         mId = id;
         loadKeyboard(context, xmlLayoutResId);
-        mProximityInfo = new ProximityInfo(mDisplayWidth, mDisplayHeight, GRID_WIDTH, GRID_HEIGHT);
+        mProximityInfo = new ProximityInfo(GRID_WIDTH, GRID_HEIGHT);
     }
 
     public int getProximityInfo() {
@@ -378,7 +378,7 @@ public class Keyboard {
                 mGridNeighbors[(y / mCellHeight) * GRID_WIDTH + (x / mCellWidth)] = cell;
             }
         }
-        mProximityInfo.setProximityInfo(mGridNeighbors);
+        mProximityInfo.setProximityInfo(mGridNeighbors, getMinWidth(), getHeight(), mKeys);
     }
 
     public boolean isInside(Key key, int x, int y) {
diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index fcada3762460c86cb6626666cd17b7dc86203fce..80d6de952da01df864285e37b4a0c18d02348615 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -18,18 +18,17 @@ package com.android.inputmethod.keyboard;
 
 import com.android.inputmethod.latin.Utils;
 
+import java.util.Arrays;
+import java.util.List;
+
 public class ProximityInfo {
     public static final int MAX_PROXIMITY_CHARS_SIZE = 16;
 
-    private final int mDisplayWidth;
-    private final int mDisplayHeight;
     private final int mGridWidth;
     private final int mGridHeight;
     private final int mGridSize;
 
-    ProximityInfo(int displayWidth, int displayHeight, int gridWidth, int gridHeight) {
-        mDisplayWidth = displayWidth;
-        mDisplayHeight = displayHeight;
+    ProximityInfo(int gridWidth, int gridHeight) {
         mGridWidth = gridWidth;
         mGridHeight = gridHeight;
         mGridSize = mGridWidth * mGridHeight;
@@ -43,20 +42,19 @@ public class ProximityInfo {
             int displayHeight, int gridWidth, int gridHeight, int[] proximityCharsArray);
     private native void releaseProximityInfoNative(int nativeProximityInfo);
 
-    public final void setProximityInfo(int[][] gridNeighbors) {
+    public final void setProximityInfo(int[][] gridNeighborKeyIndexes, int keyboardWidth,
+            int keyboardHeight, List<Key> keys) {
         int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE];
+        Arrays.fill(proximityCharsArray, KeyDetector.NOT_A_CODE);
         for (int i = 0; i < mGridSize; ++i) {
-            final int proximityCharsLength = gridNeighbors[i].length;
-            for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE; ++j) {
-                int charCode = KeyDetector.NOT_A_KEY;
-                if (j < proximityCharsLength) {
-                    charCode = gridNeighbors[i][j];
-                }
-                proximityCharsArray[i * MAX_PROXIMITY_CHARS_SIZE + j] = charCode;
+            final int proximityCharsLength = gridNeighborKeyIndexes[i].length;
+            for (int j = 0; j < proximityCharsLength; ++j) {
+                proximityCharsArray[i * MAX_PROXIMITY_CHARS_SIZE + j] =
+                        keys.get(gridNeighborKeyIndexes[i][j]).mCode;
             }
         }
         mNativeProximityInfo = setProximityInfoNative(MAX_PROXIMITY_CHARS_SIZE,
-                mDisplayWidth, mDisplayHeight, mGridWidth, mGridHeight, proximityCharsArray);
+                keyboardWidth, keyboardHeight, mGridWidth, mGridHeight, proximityCharsArray);
     }
 
     // TODO: Get rid of this function's input (keyboard).
diff --git a/native/src/defines.h b/native/src/defines.h
index 5d85b7c517d4ff80f82edd529e80af1d17deadb4..9534f8a873cff59be10324a9f6b842e4d0000c8e 100644
--- a/native/src/defines.h
+++ b/native/src/defines.h
@@ -129,10 +129,13 @@ static void prof_out(void) {
 #define DICTIONARY_HEADER_SIZE 2
 #define NOT_VALID_WORD -99
 
+#define KEYCODE_SPACE ' '
+
 #define SUGGEST_WORDS_WITH_MISSING_CHARACTER true
 #define SUGGEST_WORDS_WITH_MISSING_SPACE_CHARACTER true
 #define SUGGEST_WORDS_WITH_EXCESSIVE_CHARACTER true
 #define SUGGEST_WORDS_WITH_TRANSPOSED_CHARACTERS true
+#define SUGGEST_WORDS_WITH_SPACE_PROXIMITY true
 
 // The following "rate"s are used as a multiplier before dividing by 100, so they are in percent.
 #define WORDS_WITH_MISSING_CHARACTER_DEMOTION_RATE 75
diff --git a/native/src/proximity_info.cpp b/native/src/proximity_info.cpp
index d0cba3eb67d15e610c5d84cb93ace3d978c44a57..5f2d09f5cc18dac39600b838b6e179e2b92630a8 100644
--- a/native/src/proximity_info.cpp
+++ b/native/src/proximity_info.cpp
@@ -17,18 +17,48 @@
 #include <stdio.h>
 #include <string.h>
 
+#define LOG_TAG "LatinIME: proximity_info.cpp"
+
 #include "proximity_info.h"
 
 namespace latinime {
-ProximityInfo::ProximityInfo(int maxProximityCharsSize, int displayWidth, int displayHeight,
-        int gridWidth, int gridHeight, uint32_t const *proximityCharsArray)
-        : MAX_PROXIMITY_CHARS_SIZE(maxProximityCharsSize), DISPLAY_WIDTH(displayWidth),
-          DISPLAY_HEIGHT(displayHeight), GRID_WIDTH(gridWidth), GRID_HEIGHT(gridHeight) {
-    mProximityCharsArray = new uint32_t[GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE];
-    memcpy(mProximityCharsArray, proximityCharsArray, sizeof(mProximityCharsArray));
+ProximityInfo::ProximityInfo(const int maxProximityCharsSize, const int keyboardWidth,
+        const int keyboardHeight, const int gridWidth, const int gridHeight,
+        const uint32_t *proximityCharsArray)
+        : MAX_PROXIMITY_CHARS_SIZE(maxProximityCharsSize), KEYBOARD_WIDTH(keyboardWidth),
+          KEYBOARD_HEIGHT(keyboardHeight), GRID_WIDTH(gridWidth), GRID_HEIGHT(gridHeight),
+          CELL_WIDTH((keyboardWidth + gridWidth - 1) / gridWidth),
+          CELL_HEIGHT((keyboardHeight + gridHeight - 1) / gridHeight) {
+    const int len = GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE;
+    mProximityCharsArray = new uint32_t[len];
+    if (DEBUG_PROXIMITY_INFO) {
+        LOGI("Create proximity info array %d", len);
+    }
+    memcpy(mProximityCharsArray, proximityCharsArray, len * sizeof(mProximityCharsArray[0]));
 }
 
 ProximityInfo::~ProximityInfo() {
     delete[] mProximityCharsArray;
 }
+
+inline int ProximityInfo::getStartIndexFromCoordinates(const int x, const int y) const {
+    return (y / CELL_HEIGHT) * GRID_WIDTH + (x / CELL_WIDTH)
+            * MAX_PROXIMITY_CHARS_SIZE;
+}
+
+bool ProximityInfo::hasSpaceProximity(const int x, const int y) const {
+    const int startIndex = getStartIndexFromCoordinates(x, y);
+    if (DEBUG_PROXIMITY_INFO) {
+        LOGI("hasSpaceProximity: index %d", startIndex);
+    }
+    for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) {
+        if (DEBUG_PROXIMITY_INFO) {
+            LOGI("Index: %d", mProximityCharsArray[startIndex + i]);
+        }
+        if (mProximityCharsArray[startIndex + i] == KEYCODE_SPACE) {
+            return true;
+        }
+    }
+    return false;
 }
+}  // namespace latinime
diff --git a/native/src/proximity_info.h b/native/src/proximity_info.h
index 54e99505937c4571e37768dad74084fee562caf4..0f120186697102a1d4a549282ddc328c02642780 100644
--- a/native/src/proximity_info.h
+++ b/native/src/proximity_info.h
@@ -25,15 +25,20 @@ namespace latinime {
 
 class ProximityInfo {
 public:
-    ProximityInfo(int maxProximityCharsSize, int displayWidth, int displayHeight, int gridWidth,
-            int gridHeight, uint32_t const *proximityCharsArray);
+    ProximityInfo(const int maxProximityCharsSize, const int keyboardWidth,
+            const int keybaordHeight, const int gridWidth, const int gridHeight,
+            const uint32_t *proximityCharsArray);
     ~ProximityInfo();
+    bool hasSpaceProximity(const int x, const int y) const;
 private:
-    const int MAX_PROXIMITY_CHARS_SIZE;
-    const int DISPLAY_WIDTH;
-    const int DISPLAY_HEIGHT;
+    int getStartIndexFromCoordinates(const int x, const int y) const;
+    const int CELL_WIDTH;
+    const int CELL_HEIGHT;
+    const int KEYBOARD_WIDTH;
+    const int KEYBOARD_HEIGHT;
     const int GRID_WIDTH;
     const int GRID_HEIGHT;
+    const int MAX_PROXIMITY_CHARS_SIZE;
     uint32_t *mProximityCharsArray;
 };
 }; // namespace latinime
diff --git a/native/src/unigram_dictionary.cpp b/native/src/unigram_dictionary.cpp
index b82910a40103887a47ed1e19686e408b227edc9a..274e1f6d3fb4de21ceea967d02c03cb95c02a85d 100644
--- a/native/src/unigram_dictionary.cpp
+++ b/native/src/unigram_dictionary.cpp
@@ -142,7 +142,7 @@ int UnigramDictionary::getSuggestions(const ProximityInfo *proximityInfo, const
                 outWords, frequencies);
     }
 
-    PROF_START(6);
+    PROF_START(20);
     // Get the word count
     int suggestedWordsCount = 0;
     while (suggestedWordsCount < MAX_WORDS && mFrequencies[suggestedWordsCount] > 0) {
@@ -158,7 +158,7 @@ int UnigramDictionary::getSuggestions(const ProximityInfo *proximityInfo, const
             }
         }
     }
-    PROF_END(6);
+    PROF_END(20);
     PROF_CLOSE;
     return suggestedWordsCount;
 }
@@ -172,12 +172,6 @@ void UnigramDictionary::getWordSuggestions(const ProximityInfo *proximityInfo,
     initSuggestions(codes, codesSize, outWords, frequencies);
     if (DEBUG_DICT) assert(codesSize == mInputLength);
 
-    if (DEBUG_PROXIMITY_INFO) {
-        for (int i = 0; i < codesSize; ++i) {
-            LOGI("Input[%d] x = %d, y = %d", i, xcoordinates[i], ycoordinates[i]);
-        }
-    }
-
     const int MAX_DEPTH = min(mInputLength * MAX_DEPTH_MULTIPLIER, MAX_WORD_LENGTH);
     PROF_END(0);
 
@@ -227,6 +221,25 @@ void UnigramDictionary::getWordSuggestions(const ProximityInfo *proximityInfo,
         }
     }
     PROF_END(5);
+
+    PROF_START(6);
+    if (SUGGEST_WORDS_WITH_SPACE_PROXIMITY) {
+        // The first and last "mistyped spaces" are taken care of by excessive character handling
+        for (int i = 1; i < codesSize - 1; ++i) {
+            if (DEBUG_DICT) LOGI("--- Suggest words with proximity space %d", i);
+            const int x = xcoordinates[i];
+            const int y = ycoordinates[i];
+            if (DEBUG_PROXIMITY_INFO)
+                LOGI("Input[%d] x = %d, y = %d, has space proximity = %d",
+                        i, x, y, proximityInfo->hasSpaceProximity(x, y));
+
+            if (proximityInfo->hasSpaceProximity(x, y)) {
+                getMistypedSpaceWords(mInputLength, i);
+            }
+
+        }
+    }
+    PROF_END(6);
 }
 
 void UnigramDictionary::initSuggestions(const int *codes, const int codesSize,
@@ -387,27 +400,31 @@ inline static void multiplyRate(const int rate, int *freq) {
     }
 }
 
-bool UnigramDictionary::getMissingSpaceWords(const int inputLength, const int missingSpacePos) {
-    if (missingSpacePos <= 0 || missingSpacePos >= inputLength
-            || inputLength >= MAX_WORD_LENGTH) return false;
-    const int newWordLength = inputLength + 1;
+bool UnigramDictionary::getSplitTwoWordsSuggestion(const int inputLength,
+        const int firstWordStartPos, const int firstWordLength, const int secondWordStartPos,
+        const int secondWordLength) {
+    if (inputLength >= MAX_WORD_LENGTH) return false;
+    if (0 >= firstWordLength || 0 >= secondWordLength || firstWordStartPos >= secondWordStartPos
+            || firstWordStartPos < 0 || secondWordStartPos >= inputLength)
+        return false;
+    const int newWordLength = firstWordLength + secondWordLength + 1;
     // Allocating variable length array on stack
     unsigned short word[newWordLength];
-    const int firstFreq = getBestWordFreq(0, missingSpacePos, mWord);
+    const int firstFreq = getBestWordFreq(firstWordStartPos, firstWordLength, mWord);
     if (DEBUG_DICT) LOGI("First freq: %d", firstFreq);
     if (firstFreq <= 0) return false;
 
-    for (int i = 0; i < missingSpacePos; ++i) {
+    for (int i = 0; i < firstWordLength; ++i) {
         word[i] = mWord[i];
     }
 
-    const int secondFreq = getBestWordFreq(missingSpacePos, inputLength - missingSpacePos, mWord);
+    const int secondFreq = getBestWordFreq(secondWordStartPos, secondWordLength, mWord);
     if (DEBUG_DICT) LOGI("Second  freq:  %d", secondFreq);
     if (secondFreq <= 0) return false;
 
-    word[missingSpacePos] = SPACE;
-    for (int i = (missingSpacePos + 1); i < newWordLength; ++i) {
-        word[i] = mWord[i - missingSpacePos - 1];
+    word[firstWordLength] = SPACE;
+    for (int i = (firstWordLength + 1); i < newWordLength; ++i) {
+        word[i] = mWord[i - firstWordLength - 1];
     }
 
     int pairFreq = ((firstFreq + secondFreq) / 2);
@@ -417,6 +434,17 @@ bool UnigramDictionary::getMissingSpaceWords(const int inputLength, const int mi
     return true;
 }
 
+bool UnigramDictionary::getMissingSpaceWords(const int inputLength, const int missingSpacePos) {
+    return getSplitTwoWordsSuggestion(
+            inputLength, 0, missingSpacePos, missingSpacePos, inputLength - missingSpacePos);
+}
+
+bool UnigramDictionary::getMistypedSpaceWords(const int inputLength, const int spaceProximityPos) {
+    return getSplitTwoWordsSuggestion(
+            inputLength, 0, spaceProximityPos, spaceProximityPos + 1,
+            inputLength - spaceProximityPos - 1);
+}
+
 // Keep this for comparing spec to new getWords
 void UnigramDictionary::getWordsOld(const int initialPos, const int inputLength, const int skipPos,
         const int excessivePos, const int transposedPos,int *nextLetters,
diff --git a/native/src/unigram_dictionary.h b/native/src/unigram_dictionary.h
index 8a4b40e0cd59a455c4051b4f572444f8fad8ec5b..7359481a8642d7125101c59041c4e8c65fd731ca 100644
--- a/native/src/unigram_dictionary.h
+++ b/native/src/unigram_dictionary.h
@@ -64,7 +64,11 @@ private:
             const bool traverseAllNodes, const int snr, const int inputIndex, const int diffs,
             const int skipPos, const int excessivePos, const int transposedPos, int *nextLetters,
             const int nextLettersSize);
+    bool getSplitTwoWordsSuggestion(const int inputLength,
+            const int firstWordStartPos, const int firstWordLength,
+            const int secondWordStartPos, const int secondWordLength);
     bool getMissingSpaceWords(const int inputLength, const int missingSpacePos);
+    bool getMistypedSpaceWords(const int inputLength, const int spaceProximityPos);
     // Keep getWordsOld for comparing performance between getWords and getWordsOld
     void getWordsOld(const int initialPos, const int inputLength, const int skipPos,
             const int excessivePos, const int transposedPos, int *nextLetters,