diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
index ea3f6236ab7f4d57968e9e759d20bbcdbf600bb0..d342c6df07b22099da7bd04f99eed77dc3857781 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
@@ -260,12 +260,19 @@ public class KeyDetector {
         final int touchX = getTouchX(x);
         final int touchY = getTouchY(y);
 
-        for (final Key key : mKeyboard.getNearestKeys(touchX, touchY)) {
-            if (key.isOnKey(touchX, touchY)) {
-                return key;
+        int minDistance = Integer.MAX_VALUE;
+        Key primaryKey = null;
+        for (final Key key: mKeyboard.getNearestKeys(touchX, touchY)) {
+            final boolean isOnKey = key.isOnKey(touchX, touchY);
+            final int distance = key.squaredDistanceToEdge(touchX, touchY);
+            // TODO: need to take care of hitbox overlaps
+            if (primaryKey == null || distance < minDistance
+                    || (distance == minDistance && isOnKey)) {
+                minDistance = distance;
+                primaryKey = key;
             }
         }
-        return null;
+        return primaryKey;
     }
 
     public static String printableCode(Key key) {
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index a9609310c2b7b9637864fca01d726f42211df94b..251063ec436133cc13e5d1b8584edbd923dc2316 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -140,8 +140,8 @@ public class WordComposer {
             keyX = x;
             keyY = y;
         } else {
-            codes = keyDetector.newCodeArray();
-            keyDetector.getNearbyCodes(x, y, codes);
+            final Key key = keyDetector.detectHitKey(x, y);
+            codes = new int[] { key != null ? key.mCode : NOT_A_CODE };
             keyX = keyDetector.getTouchX(x);
             keyY = keyDetector.getTouchY(y);
         }
diff --git a/native/src/proximity_info.cpp b/native/src/proximity_info.cpp
index dd60ed62cd68ae342fd96340ddd9f0c6c9e4186f..4d03f3274017df2d343ca196ffbbd9dda7b04ff3 100644
--- a/native/src/proximity_info.cpp
+++ b/native/src/proximity_info.cpp
@@ -55,6 +55,7 @@ ProximityInfo::ProximityInfo(const std::string localeStr, const int maxProximity
           mTouchPositionCorrectionEnabled(false) {
     const int proximityGridLength = GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE;
     mProximityCharsArray = new int32_t[proximityGridLength];
+    mInputCodes = new int32_t[MAX_PROXIMITY_CHARS_SIZE * MAX_WORD_LENGTH_INTERNAL];
     if (DEBUG_PROXIMITY_INFO) {
         AKLOGI("Create proximity info array %d", proximityGridLength);
     }
@@ -96,6 +97,7 @@ void ProximityInfo::initializeCodeToKeyIndex() {
 ProximityInfo::~ProximityInfo() {
     delete[] mNormalizedSquaredDistances;
     delete[] mProximityCharsArray;
+    delete[] mInputCodes;
 }
 
 inline int ProximityInfo::getStartIndexFromCoordinates(const int x, const int y) const {
@@ -138,7 +140,7 @@ bool ProximityInfo::isOnKey(const int keyId, const int x, const int y) {
 int ProximityInfo::squaredDistanceToEdge(const int keyId, const int x, const int y) {
     const int left = mKeyXCoordinates[keyId];
     const int top = mKeyYCoordinates[keyId];
-    const int right = left + mKeyWidths[keyId] + 1;
+    const int right = left + mKeyWidths[keyId];
     const int bottom = top + mKeyHeights[keyId];
     const int edgeX = x < left ? left : (x > right ? right : x);
     const int edgeY = y < top ? top : (y > bottom ? bottom : y);
@@ -157,10 +159,10 @@ void ProximityInfo::calculateNearbyKeyCodes(
         if (c < KEYCODE_SPACE || c == primaryKey) {
             continue;
         }
-        int keyIndex = getKeyIndex(c);
+        const int keyIndex = getKeyIndex(c);
         const bool onKey = isOnKey(keyIndex, x, y);
         const int distance = squaredDistanceToEdge(keyIndex, x, y);
-        if (onKey || distance < MOST_COMMON_KEY_WIDTH_SQUARE) {
+        if (c >= KEYCODE_SPACE && (onKey || distance < MOST_COMMON_KEY_WIDTH_SQUARE)) {
             inputCodes[insertPos++] = c;
             if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) {
                 if (DEBUG_DICT) {
@@ -170,17 +172,17 @@ void ProximityInfo::calculateNearbyKeyCodes(
             }
         }
     }
-    inputCodes[insertPos++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE;
-    if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) {
-        if (DEBUG_DICT) {
-            assert(false);
-        }
-        return;
-    }
-
     const int additionalProximitySize =
             AdditionalProximityChars::getAdditionalCharsSize(&mLocaleStr, primaryKey);
     if (additionalProximitySize > 0) {
+        inputCodes[insertPos++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE;
+        if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) {
+            if (DEBUG_DICT) {
+                assert(false);
+            }
+            return;
+        }
+
         const int32_t* additionalProximityChars =
                 AdditionalProximityChars::getAdditionalChars(&mLocaleStr, primaryKey);
         for (int j = 0; j < additionalProximitySize; ++j) {
@@ -204,13 +206,46 @@ void ProximityInfo::calculateNearbyKeyCodes(
         }
     }
     // Add a delimiter for the proximity characters
-    inputCodes[insertPos] = 0;
+    for (int i = insertPos; i < MAX_PROXIMITY_CHARS_SIZE; ++i) {
+        inputCodes[i] = NOT_A_CODE;
+    }
 }
 
 // TODO: Calculate nearby codes here.
-void ProximityInfo::setInputParams(const int* inputCodes, const int inputLength,
+void ProximityInfo::setInputParams(const int32_t* inputCodes, const int inputLength,
         const int* xCoordinates, const int* yCoordinates) {
-    mInputCodes = inputCodes;
+    memset(mInputCodes, 0,
+            MAX_WORD_LENGTH_INTERNAL * MAX_PROXIMITY_CHARS_SIZE * sizeof(mInputCodes[0]));
+
+    for (int i = 0; i < inputLength; ++i) {
+        const int32_t primaryKey = inputCodes[i * MAX_PROXIMITY_CHARS_SIZE];
+        const int x = xCoordinates[i];
+        const int y = yCoordinates[i];
+        int *proximities = &mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE];
+        calculateNearbyKeyCodes(x, y, primaryKey, proximities);
+    }
+
+    if (DEBUG_PROXIMITY_CHARS) {
+        for (int i = 0; i < inputLength; ++i) {
+            AKLOGI("---");
+            for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE; ++j) {
+                int icc = mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE + j];
+                int icfjc = inputCodes[i * MAX_PROXIMITY_CHARS_SIZE + j];
+                icc+= 0;
+                icfjc += 0;
+                AKLOGI("--- (%d)%c,%c", i, icc, icfjc);
+                AKLOGI("---             A<%d>,B<%d>", icc, icfjc);
+            }
+        }
+    }
+    //Keep for debug, sorry
+    //for (int i = 0; i < MAX_WORD_LENGTH_INTERNAL * MAX_PROXIMITY_CHARS_SIZE; ++i) {
+    //if (i < inputLength * MAX_PROXIMITY_CHARS_SIZE) {
+    //mInputCodes[i] = mInputCodesFromJava[i];
+    //} else {
+    // mInputCodes[i] = 0;
+    // }
+    //}
     mInputXCoordinates = xCoordinates;
     mInputYCoordinates = yCoordinates;
     mTouchPositionCorrectionEnabled =
@@ -246,8 +281,9 @@ void ProximityInfo::setInputParams(const int* inputCodes, const int inputLength,
         }
         for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE && proximityChars[j] > 0; ++j) {
             const int currentChar = proximityChars[j];
-            const int keyIndex = getKeyIndex(currentChar);
-            const float squaredDistance = calculateNormalizedSquaredDistance(keyIndex, i);
+            const float squaredDistance = hasInputCoordinates()
+                    ? calculateNormalizedSquaredDistance(getKeyIndex(currentChar), i)
+                    : NOT_A_DISTANCE_FLOAT;
             if (squaredDistance >= 0.0f) {
                 mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] =
                         (int)(squaredDistance * NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR);
@@ -267,7 +303,6 @@ inline float square(const float x) { return x * x; }
 
 float ProximityInfo::calculateNormalizedSquaredDistance(
         const int keyIndex, const int inputIndex) const {
-    static const float NOT_A_DISTANCE_FLOAT = -1.0f;
     if (keyIndex == NOT_A_INDEX) {
         return NOT_A_DISTANCE_FLOAT;
     }
@@ -282,8 +317,12 @@ float ProximityInfo::calculateNormalizedSquaredDistance(
     return squaredDistance / squaredRadius;
 }
 
+bool ProximityInfo::hasInputCoordinates() const {
+    return mInputXCoordinates && mInputYCoordinates;
+}
+
 int ProximityInfo::getKeyIndex(const int c) const {
-    if (KEY_COUNT == 0 || !mInputXCoordinates || !mInputYCoordinates) {
+    if (KEY_COUNT == 0) {
         // We do not have the coordinate data
         return NOT_A_INDEX;
     }
diff --git a/native/src/proximity_info.h b/native/src/proximity_info.h
index 1a47aff848c47250f5bdd39d8807311a4c8df1ba..cdc5a3d435319ae76ddb74b7c69be9dfe762f09d 100644
--- a/native/src/proximity_info.h
+++ b/native/src/proximity_info.h
@@ -53,7 +53,7 @@ class ProximityInfo {
             const float *sweetSpotCenterYs, const float *sweetSpotRadii);
     ~ProximityInfo();
     bool hasSpaceProximity(const int x, const int y) const;
-    void setInputParams(const int *inputCodes, const int inputLength,
+    void setInputParams(const int32_t *inputCodes, const int inputLength,
             const int *xCoordinates, const int *yCoordinates);
     const int* getProximityCharsAt(const int index) const;
     unsigned short getPrimaryCharAt(const int index) const;
@@ -77,12 +77,15 @@ class ProximityInfo {
     static const int MAX_KEY_COUNT_IN_A_KEYBOARD = 64;
     // The upper limit of the char code in mCodeToKeyIndex
     static const int MAX_CHAR_CODE = 127;
+    static const float NOT_A_DISTANCE_FLOAT = -1.0f;
+    static const int NOT_A_CODE = -1;
 
     int getStartIndexFromCoordinates(const int x, const int y) const;
     void initializeCodeToKeyIndex();
     float calculateNormalizedSquaredDistance(const int keyIndex, const int inputIndex) const;
     float calculateSquaredDistanceFromSweetSpotCenter(
             const int keyIndex, const int inputIndex) const;
+    bool hasInputCoordinates() const;
     int getKeyIndex(const int c) const;
     bool hasSweetSpotData(const int keyIndex) const {
         // When there are no calibration data for a key,
@@ -105,7 +108,9 @@ class ProximityInfo {
     const int KEY_COUNT;
     const bool HAS_TOUCH_POSITION_CORRECTION_DATA;
     const std::string mLocaleStr;
-    const int *mInputCodes;
+    // TODO: remove this
+    const int *mInputCodesFromJava;
+    int32_t *mInputCodes;
     const int *mInputXCoordinates;
     const int *mInputYCoordinates;
     bool mTouchPositionCorrectionEnabled;