diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
index 734a55a79acd95aad93ca68d21592cfed1a8d67d..098af214eb7ad03d524be964719321c687ba6357 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
@@ -24,16 +24,20 @@ public interface KeyboardActionListener {
      *
      * @param primaryCode the unicode of the key being pressed. If the touch is not on a valid key,
      *            the value will be zero.
+     * @param withSliding true if pressing has occurred because the user slid finger from other key
+     *             to this key without releasing the finger.
      */
-    public void onPress(int primaryCode);
+    public void onPress(int primaryCode, boolean withSliding);
 
     /**
      * Called when the user releases a key. This is sent after the {@link #onCodeInput} is called.
      * For keys that repeat, this is only called once.
      *
      * @param primaryCode the code of the key that was released
+     * @param withSliding true if releasing has occurred because the user slid finger from the key
+     *             to other key without releasing the finger.
      */
-    public void onRelease(int primaryCode);
+    public void onRelease(int primaryCode, boolean withSliding);
 
     /**
      * Send a key code to the listener.
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 6651f9ffaae4925ceb19a66686a0c14749c36664..3d34e71a01556246fc19dbe93237243182539f33 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -440,7 +440,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
         updateShiftState();
     }
 
-    public void onPressShift() {
+    public void onPressShift(boolean withSliding) {
         if (!isKeyboardAvailable())
             return;
         // If accessibility is enabled, disable momentary shift lock.
@@ -450,7 +450,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
         if (DEBUG_STATE)
             Log.d(TAG, "onPressShift:"
                     + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
-                    + " shiftKeyState=" + shiftKeyState);
+                    + " shiftKeyState=" + shiftKeyState + " sliding=" + withSliding);
         if (isAlphabetMode()) {
             if (isShiftLocked()) {
                 // Shift key is pressed while caps lock state, we will treat this state as shifted
@@ -478,7 +478,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
         }
     }
 
-    public void onReleaseShift() {
+    public void onReleaseShift(boolean withSliding) {
         if (!isKeyboardAvailable())
             return;
         // If accessibility is enabled, disable momentary shift lock.
@@ -488,18 +488,20 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
         if (DEBUG_STATE)
             Log.d(TAG, "onReleaseShift:"
                     + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
-                    + " shiftKeyState=" + shiftKeyState);
+                    + " shiftKeyState=" + shiftKeyState + " sliding=" + withSliding);
         if (isAlphabetMode()) {
             if (shiftKeyState.isMomentary()) {
                 // After chording input while normal state.
                 toggleShift();
-            } else if (isShiftLocked() && !shiftKeyState.isIgnoring()) {
+            } else if (isShiftLocked() && !shiftKeyState.isIgnoring() && !withSliding) {
                 // Shift has been pressed without chording while caps lock state.
                 toggleCapsLock();
-            } else if (isShiftedOrShiftLocked() && shiftKeyState.isPressingOnShifted()) {
+            } else if (isShiftedOrShiftLocked() && shiftKeyState.isPressingOnShifted()
+                    && !withSliding) {
                 // Shift has been pressed without chording while shifted state.
                 toggleShift();
-            } else if (isManualTemporaryUpperCaseFromAuto() && shiftKeyState.isPressing()) {
+            } else if (isManualTemporaryUpperCaseFromAuto() && shiftKeyState.isPressing()
+                    && !withSliding) {
                 // Shift has been pressed without chording while manual temporary upper case
                 // transited from automatic temporary upper case.
                 toggleShift();
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 851430fb89583b8bf2fb3756949d987a6979eac4..61af15b1d91aad9df1a996d346598f693ecca2be 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -1094,12 +1094,12 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
                 // Nothing to do.
             }
             @Override
-            public void onPress(int primaryCode) {
-                mKeyboardActionListener.onPress(primaryCode);
+            public void onPress(int primaryCode, boolean withSliding) {
+                mKeyboardActionListener.onPress(primaryCode, withSliding);
             }
             @Override
-            public void onRelease(int primaryCode) {
-                mKeyboardActionListener.onRelease(primaryCode);
+            public void onRelease(int primaryCode, boolean withSliding) {
+                mKeyboardActionListener.onRelease(primaryCode, withSliding);
             }
         });
         // Override default ProximityKeyDetector.
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 8e9d02247f81babe3d08204f6da07f2ad48f6d8d..7468578199cc040135dd918a22da284e6cd5738e 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -93,9 +93,9 @@ public class PointerTracker {
     // Empty {@link KeyboardActionListener}
     private static final KeyboardActionListener EMPTY_LISTENER = new KeyboardActionListener() {
         @Override
-        public void onPress(int primaryCode) {}
+        public void onPress(int primaryCode, boolean withSliding) {}
         @Override
-        public void onRelease(int primaryCode) {}
+        public void onRelease(int primaryCode, boolean withSliding) {}
         @Override
         public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) {}
         @Override
@@ -138,11 +138,11 @@ public class PointerTracker {
     }
 
     // Returns true if keyboard has been changed by this callback.
-    private boolean callListenerOnPressAndCheckKeyboardLayoutChange(Key key) {
+    private boolean callListenerOnPressAndCheckKeyboardLayoutChange(Key key, boolean withSliding) {
         if (DEBUG_LISTENER)
-            Log.d(TAG, "onPress    : " + keyCodePrintable(key.mCode));
+            Log.d(TAG, "onPress    : " + keyCodePrintable(key.mCode) + " sliding=" + withSliding);
         if (key.mEnabled) {
-            mListener.onPress(key.mCode);
+            mListener.onPress(key.mCode, withSliding);
             final boolean keyboardLayoutHasBeenChanged = mKeyboardLayoutHasBeenChanged;
             mKeyboardLayoutHasBeenChanged = false;
             return keyboardLayoutHasBeenChanged;
@@ -169,11 +169,11 @@ public class PointerTracker {
 
     // Note that we need primaryCode argument because the keyboard may in shifted state and the
     // primaryCode is different from {@link Key#mCode}.
-    private void callListenerOnRelease(Key key, int primaryCode) {
+    private void callListenerOnRelease(Key key, int primaryCode, boolean withSliding) {
         if (DEBUG_LISTENER)
-            Log.d(TAG, "onRelease  : " + keyCodePrintable(primaryCode));
+            Log.d(TAG, "onRelease  : " + keyCodePrintable(primaryCode) + " sliding=" + withSliding);
         if (key.mEnabled)
-            mListener.onRelease(primaryCode);
+            mListener.onRelease(primaryCode, withSliding);
     }
 
     private void callListenerOnCancelInput() {
@@ -333,7 +333,7 @@ public class PointerTracker {
             // 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]))
+            if (callListenerOnPressAndCheckKeyboardLayoutChange(mKeys[keyIndex], false))
                 keyIndex = mKeyState.onDownKey(x, y, eventTime);
         }
         if (isValidKeyIndex(keyIndex)) {
@@ -368,7 +368,7 @@ public class PointerTracker {
                 // 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)))
+                if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), true))
                     keyIndex = keyState.onMoveKey(x, y);
                 keyState.onMoveToNewKey(keyIndex, x, y);
                 startLongPressTimer(keyIndex);
@@ -377,13 +377,13 @@ public class PointerTracker {
                 // onRelease() first to notify that the previous key has been released, then call
                 // onPress() to notify that the new key is being pressed.
                 mIsInSlidingKeyInput = true;
-                callListenerOnRelease(oldKey, oldKey.mCode);
+                callListenerOnRelease(oldKey, oldKey.mCode, true);
                 mHandler.cancelLongPressTimers();
                 if (mIsAllowedSlidingKeyInput) {
                     // 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)))
+                    if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), true))
                         keyIndex = keyState.onMoveKey(x, y);
                     keyState.onMoveToNewKey(keyIndex, x, y);
                     startLongPressTimer(keyIndex);
@@ -412,7 +412,7 @@ public class PointerTracker {
                 // The pointer has been slid out from the previous key, we must call onRelease() to
                 // notify that the previous key has been released.
                 mIsInSlidingKeyInput = true;
-                callListenerOnRelease(oldKey, oldKey.mCode);
+                callListenerOnRelease(oldKey, oldKey.mCode, true);
                 mHandler.cancelLongPressTimers();
                 if (mIsAllowedSlidingKeyInput) {
                     keyState.onMoveToNewKey(keyIndex, x ,y);
@@ -568,7 +568,7 @@ public class PointerTracker {
         }
         if (key.mOutputText != null) {
             callListenerOnTextInput(key);
-            callListenerOnRelease(key, key.mCode);
+            callListenerOnRelease(key, key.mCode, false);
         } else {
             int code = key.mCode;
             final int[] codes = mKeyDetector.newCodeArray();
@@ -590,7 +590,7 @@ public class PointerTracker {
                 codes[0] = code;
             }
             callListenerOnCodeInput(key, code, codes, x, y);
-            callListenerOnRelease(key, code);
+            callListenerOnRelease(key, code, false);
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index f1b96ad5d4c05be867cc6bc5d9a3784246324390..838249a39ac1dba07675639f5774ba0403088c23 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1951,7 +1951,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
     }
 
     @Override
-    public void onPress(int primaryCode) {
+    public void onPress(int primaryCode, boolean withSliding) {
         if (mKeyboardSwitcher.isVibrateAndSoundFeedbackRequired()) {
             vibrate();
             playKeyClick(primaryCode);
@@ -1959,7 +1959,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         KeyboardSwitcher switcher = mKeyboardSwitcher;
         final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
         if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) {
-            switcher.onPressShift();
+            switcher.onPressShift(withSliding);
         } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
             switcher.onPressSymbol();
         } else {
@@ -1969,13 +1969,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
     }
 
     @Override
-    public void onRelease(int primaryCode) {
+    public void onRelease(int primaryCode, boolean withSliding) {
         KeyboardSwitcher switcher = mKeyboardSwitcher;
         // Reset any drag flags in the keyboard
         switcher.keyReleased();
         final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
         if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) {
-            switcher.onReleaseShift();
+            switcher.onReleaseShift(withSliding);
         } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
             switcher.onReleaseSymbol();
         }