diff --git a/java/res/values-sw600dp/config.xml b/java/res/values-sw600dp/config.xml
index 011054df32aa44ca4f08a0ca7966c0814bdbee1b..260f360c3bee106741319c982b6d7bb04418b992 100644
--- a/java/res/values-sw600dp/config.xml
+++ b/java/res/values-sw600dp/config.xml
@@ -36,6 +36,8 @@
     <bool name="config_show_mini_keyboard_at_touched_point">true</bool>
     <!-- The language is never displayed if == 0, always displayed if < 0 -->
     <integer name="config_delay_before_fadeout_language_on_spacebar">1200</integer>
+    <!-- Long pressing space will invoke IME switcher if > 0, never invoke IME switcher if == 0 -->
+    <integer name="config_long_press_space_key_timeout">0</integer>
     <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
     <string name="config_default_keyboard_theme_id" translatable="false">5</string>
     <string name="config_text_size_of_language_on_spacebar" translatable="false">medium</string>
diff --git a/java/res/values-sw768dp/config.xml b/java/res/values-sw768dp/config.xml
index 2828f9d1b9ac866edbff84d660cfb58b9b00199f..82605686abac5789e88e22e059fec7435416218a 100644
--- a/java/res/values-sw768dp/config.xml
+++ b/java/res/values-sw768dp/config.xml
@@ -35,6 +35,8 @@
     <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false -->
     <bool name="config_show_mini_keyboard_at_touched_point">true</bool>
     <integer name="config_delay_update_suggestions">180</integer>
+    <!-- Long pressing space will invoke IME switcher if > 0, never invoke IME switcher if == 0 -->
+    <integer name="config_long_press_space_key_timeout">0</integer>
     <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
     <string name="config_default_keyboard_theme_id" translatable="false">5</string>
     <string name="config_text_size_of_language_on_spacebar" translatable="false">medium</string>
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index 86eeae74a7c36521ec6a50b567246c2e358f9f4c..bc64eb2e6cd90fc4ced8d65b9e8cb8e146fbcfdc 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -60,7 +60,10 @@
     <integer name="config_keyboard_grid_width">32</integer>
     <integer name="config_keyboard_grid_height">16</integer>
     <integer name="config_long_press_key_timeout">400</integer>
+    <!-- Long pressing shift will invoke caps-lock if > 0, never invoke caps-lock if == 0 -->
     <integer name="config_long_press_shift_key_timeout">1200</integer>
+    <!-- Long pressing space will invoke IME switcher if > 0, never invoke IME switcher if == 0 -->
+    <integer name="config_long_press_space_key_timeout">1200</integer>
     <integer name="config_touch_noise_threshold_millis">40</integer>
     <integer name="config_double_spaces_turn_into_period_timeout">1100</integer>
     <dimen name="config_touch_noise_threshold_distance">2.0mm</dimen>
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
index b807dd3257fcdc4b93c0394366cddf3cd6d93392..078d89f49c5b4d211024efc8fcf3c50d604a2eb8 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
@@ -52,7 +52,6 @@ import java.util.WeakHashMap;
 public class LatinKeyboardBaseView extends KeyboardView implements PointerTracker.KeyEventHandler {
     private static final String TAG = LatinKeyboardBaseView.class.getSimpleName();
 
-    private static final boolean ENABLE_CAPSLOCK_BY_LONGPRESS = true;
     private static final boolean ENABLE_CAPSLOCK_BY_DOUBLETAP = true;
 
     // Timing constants
@@ -87,8 +86,7 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke
             implements TimerProxy {
         private static final int MSG_REPEAT_KEY = 1;
         private static final int MSG_LONGPRESS_KEY = 2;
-        private static final int MSG_LONGPRESS_SHIFT_KEY = 3;
-        private static final int MSG_IGNORE_DOUBLE_TAP = 4;
+        private static final int MSG_IGNORE_DOUBLE_TAP = 3;
 
         private boolean mInKeyRepeat;
 
@@ -108,9 +106,6 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke
             case MSG_LONGPRESS_KEY:
                 keyboardView.openMiniKeyboardIfRequired(msg.arg1, tracker);
                 break;
-            case MSG_LONGPRESS_SHIFT_KEY:
-                keyboardView.onLongPressShiftKey(tracker);
-                break;
             }
         }
 
@@ -131,29 +126,19 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke
 
         @Override
         public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker) {
-            cancelLongPressTimers();
+            cancelLongPressTimer();
             sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, keyIndex, 0, tracker), delay);
         }
 
         @Override
-        public void startLongPressShiftTimer(long delay, int keyIndex, PointerTracker tracker) {
-            cancelLongPressTimers();
-            if (ENABLE_CAPSLOCK_BY_LONGPRESS) {
-                sendMessageDelayed(
-                        obtainMessage(MSG_LONGPRESS_SHIFT_KEY, keyIndex, 0, tracker), delay);
-            }
-        }
-
-        @Override
-        public void cancelLongPressTimers() {
+        public void cancelLongPressTimer() {
             removeMessages(MSG_LONGPRESS_KEY);
-            removeMessages(MSG_LONGPRESS_SHIFT_KEY);
         }
 
         @Override
         public void cancelKeyTimers() {
             cancelKeyRepeatTimer();
-            cancelLongPressTimers();
+            cancelLongPressTimer();
             removeMessages(MSG_IGNORE_DOUBLE_TAP);
         }
 
@@ -355,11 +340,6 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke
         return onLongPress(parentKey, tracker);
     }
 
-    private void onLongPressShiftKey(PointerTracker tracker) {
-        tracker.onLongPressed();
-        mKeyboardActionListener.onCodeInput(Keyboard.CODE_CAPSLOCK, null, 0, 0);
-    }
-
     private void onDoubleTapShiftKey(@SuppressWarnings("unused") PointerTracker tracker) {
         // When shift key is double tapped, the first tap is correctly processed as usual tap. And
         // the second tap is treated as this double tap event, so that we need not mark tracker
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 5f5475ce828ea915a60f4df935d83d60710f5826..617961b5912da2cde9cc80f6e54c0c32c001c618 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -95,13 +95,17 @@ public class LatinKeyboardView extends LatinKeyboardBaseView {
     @Override
     protected boolean onLongPress(Key key, PointerTracker tracker) {
         int primaryCode = key.mCode;
-        if (primaryCode == Keyboard.CODE_SETTINGS) {
+        if (primaryCode == Keyboard.CODE_SETTINGS || primaryCode == Keyboard.CODE_SPACE) {
             tracker.onLongPressed();
+            // Both long pressing settings key and space key invoke IME switcher dialog.
             return invokeOnKey(Keyboard.CODE_SETTINGS_LONGPRESS);
         } else if (primaryCode == '0' && getLatinKeyboard().isPhoneKeyboard()) {
             tracker.onLongPressed();
             // Long pressing on 0 in phone number keypad gives you a '+'.
             return invokeOnKey('+');
+        } else if (primaryCode == Keyboard.CODE_SHIFT) {
+            tracker.onLongPressed();
+            return invokeOnKey(Keyboard.CODE_CAPSLOCK);
         } else {
             return super.onLongPress(key, tracker);
         }
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index aa2f3af487e83c98667449e5eb8bd8dc1f754ff6..8d7496c54039fc9742f004b7ff91116ec7eda7da 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -73,8 +73,7 @@ public class PointerTracker {
     public interface TimerProxy {
         public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker);
         public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker);
-        public void startLongPressShiftTimer(long delay, int keyIndex, PointerTracker tracker);
-        public void cancelLongPressTimers();
+        public void cancelLongPressTimer();
         public void cancelKeyTimers();
     }
 
@@ -84,6 +83,7 @@ public class PointerTracker {
     private static int sDelayBeforeKeyRepeatStart;
     private static int sLongPressKeyTimeout;
     private static int sLongPressShiftKeyTimeout;
+    private static int sLongPressSpaceKeyTimeout;
     private static int sTouchNoiseThresholdMillis;
     private static int sTouchNoiseThresholdDistanceSquared;
 
@@ -165,6 +165,7 @@ public class PointerTracker {
         sDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start);
         sLongPressKeyTimeout = res.getInteger(R.integer.config_long_press_key_timeout);
         sLongPressShiftKeyTimeout = res.getInteger(R.integer.config_long_press_shift_key_timeout);
+        sLongPressSpaceKeyTimeout = res.getInteger(R.integer.config_long_press_space_key_timeout);
         sTouchNoiseThresholdMillis = res.getInteger(R.integer.config_touch_noise_threshold_millis);
         final float touchNoiseThresholdDistance = res.getDimension(
                 R.dimen.config_touch_noise_threshold_distance);
@@ -553,7 +554,7 @@ public class PointerTracker {
                 setReleasedKeyGraphics(oldKeyIndex);
                 callListenerOnRelease(oldKey, oldKey.mCode, true);
                 startSlidingKeyInput(oldKey);
-                mTimerProxy.cancelLongPressTimers();
+                mTimerProxy.cancelLongPressTimer();
                 if (mIsAllowedSlidingKeyInput) {
                     onMoveToNewKey(keyIndex, x, y);
                 } else {
@@ -720,7 +721,13 @@ public class PointerTracker {
     private void startLongPressTimer(int keyIndex) {
         Key key = getKey(keyIndex);
         if (key.mCode == Keyboard.CODE_SHIFT) {
-            mTimerProxy.startLongPressShiftTimer(sLongPressShiftKeyTimeout, keyIndex, this);
+            if (sLongPressShiftKeyTimeout > 0) {
+                mTimerProxy.startLongPressTimer(sLongPressShiftKeyTimeout, keyIndex, this);
+            }
+        } else if (key.mCode == Keyboard.CODE_SPACE) {
+            if (sLongPressSpaceKeyTimeout > 0) {
+                mTimerProxy.startLongPressTimer(sLongPressSpaceKeyTimeout, keyIndex, this);
+            }
         } else if (key.hasUppercaseLetter() && mKeyboard.isManualTemporaryUpperCase()) {
             // We need not start long press timer on the key which has manual temporary upper case
             // code defined and the keyboard is in manual temporary upper case mode.
diff --git a/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java b/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java
index af8e5956899c82b32c05bd9513aef798485cb26f..5ab44d0637e5ef55f10fc6e9613ccddbe0e40034 100644
--- a/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java
@@ -49,9 +49,7 @@ public class PopupMiniKeyboardView extends KeyboardView implements PopupPanel {
         @Override
         public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker) {}
         @Override
-        public void startLongPressShiftTimer(long delay, int keyIndex, PointerTracker tracker) {}
-        @Override
-        public void cancelLongPressTimers() {}
+        public void cancelLongPressTimer() {}
         @Override
         public void cancelKeyTimers() {}
     };