diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index e9a3bf2c01cb523474271311806de07d46dcc34d..49f29f9236006ad030c5cbb2666f6e455b65304d 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -65,6 +65,9 @@ public class PointerTracker {
 
     private final PointerTrackerKeyState mKeyState;
 
+    // true if keyboard layout has been changed.
+    private boolean mKeyboardLayoutHasBeenChanged;
+
     // true if event is already translated to a key action (long press or mini-keyboard)
     private boolean mKeyAlreadyProcessed;
 
@@ -122,10 +125,14 @@ public class PointerTracker {
         mListener = listener;
     }
 
-    private void callListenerOnPress(int primaryCode) {
+    // Returns true if keyboard has been changed by this callback.
+    private boolean callListenerOnPressAndCheckKeyboardLayoutChange(int primaryCode) {
         if (DEBUG_LISTENER)
             Log.d(TAG, "onPress    : " + keyCodePrintable(primaryCode));
         mListener.onPress(primaryCode);
+        final boolean keyboardLayoutHasBeenChanged = mKeyboardLayoutHasBeenChanged;
+        mKeyboardLayoutHasBeenChanged = false;
+        return keyboardLayoutHasBeenChanged;
     }
 
     private void callListenerOnCodeInput(int primaryCode, int[] keyCodes, int x, int y) {
@@ -159,8 +166,8 @@ public class PointerTracker {
         mKeyboard = keyboard;
         mKeys = keys;
         mKeyHysteresisDistanceSquared = (int)(keyHysteresisDistance * keyHysteresisDistance);
-        // Update current key index because keyboard layout has been changed.
-        mKeyState.onSetKeyboard();
+        // Mark that keyboard layout has been changed.
+        mKeyboardLayoutHasBeenChanged = true;
     }
 
     public boolean isInSlidingKeyInput() {
@@ -296,14 +303,16 @@ public class PointerTracker {
         // from modifier key, or 3) this pointer is on mini-keyboard.
         mIsAllowedSlidingKeyInput = mConfigSlidingKeyInputEnabled || isModifierInternal(keyIndex)
                 || mKeyDetector instanceof MiniKeyboardKeyDetector;
+        mKeyboardLayoutHasBeenChanged = false;
         mKeyAlreadyProcessed = false;
         mIsRepeatableKey = false;
         mIsInSlidingKeyInput = false;
         if (isValidKeyIndex(keyIndex)) {
-            callListenerOnPress(mKeys[keyIndex].mCode);
-            // This onPress call may have changed keyboard layout and have updated mKeyIndex.
-            // If that's the case, mKeyIndex has been updated in setKeyboard().
-            keyIndex = mKeyState.getKeyIndex();
+            // This onPress call may have changed keyboard layout. Those cases are detected at
+            // {@link #setKeyboard}. In those cases, we should update keyIndex according to the new
+            // keyboard layout.
+            if (callListenerOnPressAndCheckKeyboardLayoutChange(mKeys[keyIndex].mCode))
+                keyIndex = mKeyState.onDownKey(x, y, eventTime);
         }
         if (isValidKeyIndex(keyIndex)) {
             if (mKeys[keyIndex].mRepeatable) {
@@ -327,13 +336,17 @@ public class PointerTracker {
         // TODO: down-to-up filter, if (eventTime-downTime) is less than threshold, just ignore
         // this move event. Otherwise fire {@link onDownEventInternal} and continue.
 
-        final int keyIndex = keyState.onMoveKey(x, y);
+        int keyIndex = keyState.onMoveKey(x, y);
         final Key oldKey = getKey(keyState.getKeyIndex());
         if (isValidKeyIndex(keyIndex)) {
             if (oldKey == null) {
                 // The pointer has been slid in to the new key, but the finger was not on any keys.
                 // In this case, we must call onPress() to notify that the new key is being pressed.
-                callListenerOnPress(getKey(keyIndex).mCode);
+                // This onPress call may have changed keyboard layout. Those cases are detected at
+                // {@link #setKeyboard}. In those cases, we should update keyIndex according to the
+                // new keyboard layout.
+                if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex).mCode))
+                    keyIndex = keyState.onMoveKey(x, y);
                 keyState.onMoveToNewKey(keyIndex, x, y);
                 startLongPressTimer(keyIndex);
             } else if (!isMinorMoveBounce(x, y, keyIndex)) {
@@ -344,7 +357,11 @@ public class PointerTracker {
                 callListenerOnRelease(oldKey.mCode);
                 mHandler.cancelLongPressTimers();
                 if (mIsAllowedSlidingKeyInput) {
-                    callListenerOnPress(getKey(keyIndex).mCode);
+                    // This onPress call may have changed keyboard layout. Those cases are detected
+                    // at {@link #setKeyboard}. In those cases, we should update keyIndex according
+                    // to the new keyboard layout.
+                    if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex).mCode))
+                        keyIndex = keyState.onMoveKey(x, y);
                     keyState.onMoveToNewKey(keyIndex, x, y);
                     startLongPressTimer(keyIndex);
                 } else {
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTrackerKeyState.java b/java/src/com/android/inputmethod/keyboard/PointerTrackerKeyState.java
index 8b969c70acab17e6d6c0b51f3e480c51e4f6873c..250bb95eb86924c57e9caa66ff9a0dc059eac160 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTrackerKeyState.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTrackerKeyState.java
@@ -106,8 +106,4 @@ package com.android.inputmethod.keyboard;
         mUpTime = eventTime;
         return onMoveKeyInternal(x, y);
     }
-
-    public void onSetKeyboard() {
-        mKeyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(mKeyX, mKeyY, null);
-    }
 }