merge in ics-mr1-release history after reset to ics-mr1
diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_mic.png b/java/res/drawable-hdpi/sym_keyboard_feedback_mic.png
deleted file mode 100644
index a88a19d..0000000
--- a/java/res/drawable-hdpi/sym_keyboard_feedback_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_settings.png b/java/res/drawable-hdpi/sym_keyboard_feedback_settings.png
deleted file mode 100644
index 6304b00..0000000
--- a/java/res/drawable-hdpi/sym_keyboard_feedback_settings.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_settings_holo.png b/java/res/drawable-hdpi/sym_keyboard_feedback_settings_holo.png
deleted file mode 100644
index 960dd78..0000000
--- a/java/res/drawable-hdpi/sym_keyboard_feedback_settings_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_feedback_mic.png b/java/res/drawable-mdpi/sym_keyboard_feedback_mic.png
deleted file mode 100644
index 3ed0782..0000000
--- a/java/res/drawable-mdpi/sym_keyboard_feedback_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_feedback_settings.png b/java/res/drawable-mdpi/sym_keyboard_feedback_settings.png
deleted file mode 100644
index 03bad18..0000000
--- a/java/res/drawable-mdpi/sym_keyboard_feedback_settings.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_feedback_settings_holo.png b/java/res/drawable-mdpi/sym_keyboard_feedback_settings_holo.png
deleted file mode 100644
index 453991e..0000000
--- a/java/res/drawable-mdpi/sym_keyboard_feedback_settings_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_feedback_mic.png b/java/res/drawable-xhdpi/sym_keyboard_feedback_mic.png
deleted file mode 100644
index 5ac27eb..0000000
--- a/java/res/drawable-xhdpi/sym_keyboard_feedback_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_feedback_settings.png b/java/res/drawable-xhdpi/sym_keyboard_feedback_settings.png
deleted file mode 100644
index 021cafa..0000000
--- a/java/res/drawable-xhdpi/sym_keyboard_feedback_settings.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_feedback_settings_holo.png b/java/res/drawable-xhdpi/sym_keyboard_feedback_settings_holo.png
deleted file mode 100644
index bc9a629..0000000
--- a/java/res/drawable-xhdpi/sym_keyboard_feedback_settings_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index e569e83..0c9ca4f 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -180,8 +180,6 @@
         <attr name="iconShortcutForLabel" format="reference" />
         <attr name="iconShiftedShiftKey" format="reference" />
         <attr name="iconPreviewTabKey" format="reference" />
-        <attr name="iconPreviewSettingsKey" format="reference" />
-        <attr name="iconPreviewShortcutKey" format="reference" />
     </declare-styleable>
 
     <declare-styleable name="Keyboard_Key">
@@ -246,8 +244,6 @@
         <attr name="keyIconPreview" format="enum">
             <!-- This should be aligned with KeyboardIcons.ICON_PREVIEW_* -->
             <enum name="iconPreviewTabKey" value="11" />
-            <enum name="iconPreviewSettingsKey" value="12" />
-            <enum name="iconPreviewShortcutKey" value="13" />
         </attr>
         <!-- The key style to specify a set of key attributes defined by <key_style/> -->
         <attr name="keyStyle" format="string" />
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index e2422d2..3f676ab 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -63,6 +63,7 @@
     <integer name="config_long_press_space_key_timeout">@integer/config_long_press_key_timeout</integer>
     <integer name="config_touch_noise_threshold_millis">40</integer>
     <integer name="config_double_spaces_turn_into_period_timeout">1100</integer>
+    <integer name="config_ignore_special_key_timeout">700</integer>
     <dimen name="config_touch_noise_threshold_distance">2.0mm</dimen>
     <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
     <string name="config_default_keyboard_theme_id" translatable="false">5</string>
diff --git a/java/res/values/keyboard-icons-black.xml b/java/res/values/keyboard-icons-black.xml
index 23d163c..f767cb3 100644
--- a/java/res/values/keyboard-icons-black.xml
+++ b/java/res/values/keyboard-icons-black.xml
@@ -32,8 +32,6 @@
         <item name="iconShortcutForLabel">@drawable/sym_bkeyboard_label_mic</item>
         <item name="iconShiftedShiftKey">@drawable/sym_bkeyboard_shift_locked</item>
         <item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item>
-        <item name="iconPreviewSettingsKey">@drawable/sym_keyboard_feedback_settings</item>
-        <item name="iconPreviewShortcutKey">@drawable/sym_keyboard_feedback_mic</item>
         <!-- LatinKeyboard icons -->
         <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item>
         <item name="disabledShortcutIcon">@drawable/sym_bkeyboard_voice_off</item>
diff --git a/java/res/values/keyboard-icons-ics.xml b/java/res/values/keyboard-icons-ics.xml
index 28859b6..f102143 100644
--- a/java/res/values/keyboard-icons-ics.xml
+++ b/java/res/values/keyboard-icons-ics.xml
@@ -31,8 +31,6 @@
         <item name="iconShortcutForLabel">@drawable/sym_keyboard_label_mic_holo</item>
         <item name="iconShiftedShiftKey">@drawable/sym_keyboard_shift_locked_holo</item>
         <item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item>
-        <item name="iconPreviewSettingsKey">@drawable/sym_keyboard_feedback_settings_holo</item>
-        <item name="iconPreviewShortcutKey">@drawable/sym_keyboard_feedback_mic</item>
         <!-- LatinKeyboard icons -->
         <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led_holo</item>
         <item name="disabledShortcutIcon">@drawable/sym_keyboard_voice_off_holo</item>
diff --git a/java/res/values/keyboard-icons-white.xml b/java/res/values/keyboard-icons-white.xml
index a1765a4..07ece66 100644
--- a/java/res/values/keyboard-icons-white.xml
+++ b/java/res/values/keyboard-icons-white.xml
@@ -28,8 +28,6 @@
         <item name="iconShortcutForLabel">@drawable/sym_keyboard_label_mic</item>
         <item name="iconShiftedShiftKey">@drawable/sym_keyboard_shift_locked</item>
         <item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item>
-        <item name="iconPreviewSettingsKey">@drawable/sym_keyboard_feedback_settings</item>
-        <item name="iconPreviewShortcutKey">@drawable/sym_keyboard_feedback_mic</item>
         <!-- LatinKeyboard icons -->
         <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item>
         <item name="disabledShortcutIcon">@drawable/sym_keyboard_voice_off_holo</item>
diff --git a/java/res/xml-sw600dp/kbd_key_styles.xml b/java/res/xml-sw600dp/kbd_key_styles.xml
index 0b6d871..25fa8b2 100644
--- a/java/res/xml-sw600dp/kbd_key_styles.xml
+++ b/java/res/xml-sw600dp/kbd_key_styles.xml
@@ -73,13 +73,11 @@
         latin:styleName="shortcutKeyStyle"
         latin:code="@integer/key_shortcut"
         latin:keyIcon="iconShortcutKey"
-        latin:keyIconPreview="iconPreviewShortcutKey"
         latin:parentStyle="f2PopupStyle" />
     <key-style
         latin:styleName="settingsKeyStyle"
         latin:code="@integer/key_settings"
         latin:keyIcon="iconSettingsKey"
-        latin:keyIconPreview="iconPreviewSettingsKey"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="tabKeyStyle"
diff --git a/java/res/xml-sw768dp/kbd_key_styles.xml b/java/res/xml-sw768dp/kbd_key_styles.xml
index 686e7b6..f16f5b6 100644
--- a/java/res/xml-sw768dp/kbd_key_styles.xml
+++ b/java/res/xml-sw768dp/kbd_key_styles.xml
@@ -55,13 +55,11 @@
         latin:styleName="settingsKeyStyle"
         latin:code="@integer/key_settings"
         latin:keyIcon="iconSettingsKey"
-        latin:keyIconPreview="iconPreviewSettingsKey"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="shortcutKeyStyle"
         latin:code="@integer/key_shortcut"
         latin:keyIcon="iconShortcutKey"
-        latin:keyIconPreview="iconPreviewShortcutKey"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="tabKeyStyle"
diff --git a/java/res/xml/kbd_key_styles.xml b/java/res/xml/kbd_key_styles.xml
index 11b1abb..453b05d 100644
--- a/java/res/xml/kbd_key_styles.xml
+++ b/java/res/xml/kbd_key_styles.xml
@@ -154,13 +154,11 @@
         latin:styleName="shortcutKeyStyle"
         latin:code="@integer/key_shortcut"
         latin:keyIcon="iconShortcutKey"
-        latin:keyIconPreview="iconPreviewShortcutKey"
         latin:parentStyle="f1PopupStyle" />
     <key-style
         latin:styleName="settingsKeyStyle"
         latin:code="@integer/key_settings"
         latin:keyIcon="iconSettingsKey"
-        latin:keyIconPreview="iconPreviewSettingsKey"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="tabKeyStyle"
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index a57b9d1..4578507 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -170,6 +170,10 @@
         return mShiftState.isShiftLocked();
     }
 
+    public boolean isShiftLockShifted() {
+        return mShiftState.isShiftLockShifted();
+    }
+
     public boolean setShifted(boolean newShiftState) {
         for (final Key key : mShiftKeys) {
             if (!newShiftState && !mShiftState.isShiftLocked()) {
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 83871a6..ac718fc 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -386,6 +386,13 @@
         return false;
     }
 
+    private boolean isShiftLockShifted() {
+        LatinKeyboard latinKeyboard = getLatinKeyboard();
+        if (latinKeyboard != null)
+            return latinKeyboard.isShiftLockShifted();
+        return false;
+    }
+
     public boolean isAutomaticTemporaryUpperCase() {
         LatinKeyboard latinKeyboard = getLatinKeyboard();
         if (latinKeyboard != null)
@@ -559,6 +566,9 @@
             if (shiftKeyState.isMomentary()) {
                 // After chording input while normal state.
                 toggleShift();
+            } else if (isShiftLocked() && !isShiftLockShifted() && shiftKeyState.isPressing()
+                    && !withSliding) {
+                // Shift has been long pressed, ignore this release.
             } else if (isShiftLocked() && !shiftKeyState.isIgnoring() && !withSliding) {
                 // Shift has been pressed without chording while caps lock state.
                 toggleCapsLock();
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index aab52e1..6ce3876 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -351,7 +351,7 @@
         // calling setAlreadyProcessed() nor remove the tracker from mPointerQueue.
         final int primaryCode = ignore ? Keyboard.CODE_HAPTIC_AND_AUDIO_FEEDBACK_ONLY
                 : Keyboard.CODE_CAPSLOCK;
-        mKeyboardActionListener.onCodeInput(primaryCode, null, 0, 0);
+        invokeCodeInput(primaryCode);
     }
 
     // This default implementation returns a more keys panel.
@@ -399,18 +399,22 @@
             if (primaryCode == Keyboard.CODE_DIGIT0 && latinKeyboard.isPhoneKeyboard()) {
                 tracker.onLongPressed();
                 // Long pressing on 0 in phone number keypad gives you a '+'.
-                return invokeOnKey(Keyboard.CODE_PLUS);
+                invokeCodeInput(Keyboard.CODE_PLUS);
+                invokeReleaseKey(primaryCode);
+                return true;
             }
             if (primaryCode == Keyboard.CODE_SHIFT && latinKeyboard.isAlphaKeyboard()) {
                 tracker.onLongPressed();
-                return invokeOnKey(Keyboard.CODE_CAPSLOCK);
+                invokeCodeInput(Keyboard.CODE_CAPSLOCK);
+                invokeReleaseKey(primaryCode);
+                return true;
             }
         }
         if (primaryCode == Keyboard.CODE_SETTINGS || primaryCode == Keyboard.CODE_SPACE) {
             // Both long pressing settings key and space key invoke IME switcher dialog.
-            if (getKeyboardActionListener().onCustomRequest(
-                    LatinIME.CODE_SHOW_INPUT_METHOD_PICKER)) {
+            if (invokeCustomRequest(LatinIME.CODE_SHOW_INPUT_METHOD_PICKER)) {
                 tracker.onLongPressed();
+                invokeReleaseKey(primaryCode);
                 return true;
             } else {
                 return openMoreKeysPanel(parentKey, tracker);
@@ -420,11 +424,18 @@
         }
     }
 
-    private boolean invokeOnKey(int primaryCode) {
+    private boolean invokeCustomRequest(int code) {
+        return getKeyboardActionListener().onCustomRequest(code);
+    }
+
+    private void invokeCodeInput(int primaryCode) {
         getKeyboardActionListener().onCodeInput(primaryCode, null,
                 KeyboardActionListener.NOT_A_TOUCH_COORDINATE,
                 KeyboardActionListener.NOT_A_TOUCH_COORDINATE);
-        return true;
+    }
+
+    private void invokeReleaseKey(int primaryCode) {
+        getKeyboardActionListener().onRelease(primaryCode, false);
     }
 
     private boolean openMoreKeysPanel(Key parentKey, PointerTracker tracker) {
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 38c419d..198e06a 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -353,9 +353,12 @@
     // The modifier key, such as shift key, should not show its key preview.
     private static boolean isKeyPreviewRequired(Key key) {
         final int code = key.mCode;
-        if (isModifierCode(code) || code == Keyboard.CODE_DELETE
-                || code == Keyboard.CODE_ENTER || code == Keyboard.CODE_SPACE)
+        // TODO: Stop hard-coding these key codes here, and add a new key attribute of a key.
+        if (code == Keyboard.CODE_SPACE || code == Keyboard.CODE_ENTER
+                || code == Keyboard.CODE_DELETE || isModifierCode(code)
+                || code == Keyboard.CODE_SETTINGS || code == Keyboard.CODE_SHORTCUT) {
             return false;
+        }
         return true;
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index 2d8b7bf..faa5f86 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -42,10 +42,8 @@
     private static final int ICON_SHIFTED_SHIFT_KEY = 10;
     // This should be aligned with Keyboard.keyIconPreview enum.
     private static final int ICON_PREVIEW_TAB_KEY = 11;
-    private static final int ICON_PREVIEW_SETTINGS_KEY = 12;
-    private static final int ICON_PREVIEW_SHORTCUT_KEY = 13;
 
-    private static final int ICON_LAST = 13;
+    private static final int ICON_LAST = 11;
 
     private final Drawable mIcons[] = new Drawable[ICON_LAST + 1];
 
@@ -73,10 +71,6 @@
             return ICON_SHIFTED_SHIFT_KEY;
         case R.styleable.Keyboard_iconPreviewTabKey:
             return ICON_PREVIEW_TAB_KEY;
-        case R.styleable.Keyboard_iconPreviewSettingsKey:
-            return ICON_PREVIEW_SETTINGS_KEY;
-        case R.styleable.Keyboard_iconPreviewShortcutKey:
-            return ICON_PREVIEW_SHORTCUT_KEY;
         default:
             return ICON_UNDEFINED;
         }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java
index fd98456..28a53ce 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java
@@ -103,6 +103,10 @@
         return mState == SHIFT_LOCKED || mState == SHIFT_LOCK_SHIFTED;
     }
 
+    public boolean isShiftLockShifted() {
+        return mState == SHIFT_LOCK_SHIFTED;
+    }
+
     public boolean isAutomaticTemporaryUpperCase() {
         return mState == AUTO_SHIFTED;
     }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index d57154a..7ba7f7d 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -241,13 +241,40 @@
         private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 3;
         private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 4;
         private static final int MSG_SPACE_TYPED = 5;
-        private static final int MSG_SET_BIGRAM_PREDICTIONS = 6;
-        private static final int MSG_PENDING_IMS_CALLBACK = 7;
+        private static final int MSG_KEY_TYPED = 6;
+        private static final int MSG_SET_BIGRAM_PREDICTIONS = 7;
+        private static final int MSG_PENDING_IMS_CALLBACK = 8;
+
+        private int mDelayBeforeFadeoutLanguageOnSpacebar;
+        private int mDelayUpdateSuggestions;
+        private int mDelayUpdateShiftState;
+        private int mDurationOfFadeoutLanguageOnSpacebar;
+        private float mFinalFadeoutFactorOfLanguageOnSpacebar;
+        private long mDoubleSpacesTurnIntoPeriodTimeout;
+        private long mIgnoreSpecialKeyTimeout;
 
         public UIHandler(LatinIME outerInstance) {
             super(outerInstance);
         }
 
+        public void onCreate() {
+            final Resources res = getOuterInstance().getResources();
+            mDelayBeforeFadeoutLanguageOnSpacebar = res.getInteger(
+                    R.integer.config_delay_before_fadeout_language_on_spacebar);
+            mDelayUpdateSuggestions =
+                    res.getInteger(R.integer.config_delay_update_suggestions);
+            mDelayUpdateShiftState =
+                    res.getInteger(R.integer.config_delay_update_shift_state);
+            mDurationOfFadeoutLanguageOnSpacebar = res.getInteger(
+                    R.integer.config_duration_of_fadeout_language_on_spacebar);
+            mFinalFadeoutFactorOfLanguageOnSpacebar = res.getInteger(
+                    R.integer.config_final_fadeout_percentage_of_language_on_spacebar) / 100.0f;
+            mDoubleSpacesTurnIntoPeriodTimeout = res.getInteger(
+                    R.integer.config_double_spaces_turn_into_period_timeout);
+            mIgnoreSpecialKeyTimeout = res.getInteger(
+                    R.integer.config_ignore_special_key_timeout);
+        }
+
         @Override
         public void handleMessage(Message msg) {
             final LatinIME latinIme = getOuterInstance();
@@ -270,17 +297,15 @@
             case MSG_FADEOUT_LANGUAGE_ON_SPACEBAR:
                 if (inputView != null) {
                     inputView.setSpacebarTextFadeFactor(
-                            (1.0f + latinIme.mSettingsValues.
-                                    mFinalFadeoutFactorOfLanguageOnSpacebar) / 2,
+                            (1.0f + mFinalFadeoutFactorOfLanguageOnSpacebar) / 2,
                             (LatinKeyboard)msg.obj);
                 }
                 sendMessageDelayed(obtainMessage(MSG_DISMISS_LANGUAGE_ON_SPACEBAR, msg.obj),
-                        latinIme.mSettingsValues.mDurationOfFadeoutLanguageOnSpacebar);
+                        mDurationOfFadeoutLanguageOnSpacebar);
                 break;
             case MSG_DISMISS_LANGUAGE_ON_SPACEBAR:
                 if (inputView != null) {
-                    inputView.setSpacebarTextFadeFactor(
-                            latinIme.mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar,
+                    inputView.setSpacebarTextFadeFactor(mFinalFadeoutFactorOfLanguageOnSpacebar,
                             (LatinKeyboard)msg.obj);
                 }
                 break;
@@ -289,8 +314,7 @@
 
         public void postUpdateSuggestions() {
             removeMessages(MSG_UPDATE_SUGGESTIONS);
-            sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS),
-                    getOuterInstance().mSettingsValues.mDelayUpdateSuggestions);
+            sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS), mDelayUpdateSuggestions);
         }
 
         public void cancelUpdateSuggestions() {
@@ -303,8 +327,7 @@
 
         public void postUpdateShiftKeyState() {
             removeMessages(MSG_UPDATE_SHIFT_STATE);
-            sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE),
-                    getOuterInstance().mSettingsValues.mDelayUpdateShiftState);
+            sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE), mDelayUpdateShiftState);
         }
 
         public void cancelUpdateShiftState() {
@@ -313,8 +336,7 @@
 
         public void postUpdateBigramPredictions() {
             removeMessages(MSG_SET_BIGRAM_PREDICTIONS);
-            sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS),
-                    getOuterInstance().mSettingsValues.mDelayUpdateSuggestions);
+            sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS), mDelayUpdateSuggestions);
         }
 
         public void cancelUpdateBigramPredictions() {
@@ -334,26 +356,24 @@
                 final LatinKeyboard keyboard = latinIme.mKeyboardSwitcher.getLatinKeyboard();
                 // The language is always displayed when the delay is negative.
                 final boolean needsToDisplayLanguage = localeChanged
-                        || latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar < 0;
+                        || mDelayBeforeFadeoutLanguageOnSpacebar < 0;
                 // The language is never displayed when the delay is zero.
-                if (latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar != 0) {
+                if (mDelayBeforeFadeoutLanguageOnSpacebar != 0) {
                     inputView.setSpacebarTextFadeFactor(needsToDisplayLanguage ? 1.0f
-                            : latinIme.mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar,
+                            : mFinalFadeoutFactorOfLanguageOnSpacebar,
                             keyboard);
                 }
                 // The fadeout animation will start when the delay is positive.
-                if (localeChanged
-                        && latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar > 0) {
+                if (localeChanged && mDelayBeforeFadeoutLanguageOnSpacebar > 0) {
                     sendMessageDelayed(obtainMessage(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR, keyboard),
-                            latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar);
+                            mDelayBeforeFadeoutLanguageOnSpacebar);
                 }
             }
         }
 
         public void startDoubleSpacesTimer() {
             removeMessages(MSG_SPACE_TYPED);
-            sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED),
-                    getOuterInstance().mSettingsValues.mDoubleSpacesTurnIntoPeriodTimeout);
+            sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED), mDoubleSpacesTurnIntoPeriodTimeout);
         }
 
         public void cancelDoubleSpacesTimer() {
@@ -364,6 +384,15 @@
             return hasMessages(MSG_SPACE_TYPED);
         }
 
+        public void startKeyTypedTimer() {
+            removeMessages(MSG_KEY_TYPED);
+            sendMessageDelayed(obtainMessage(MSG_KEY_TYPED), mIgnoreSpecialKeyTimeout);
+        }
+
+        public boolean isIgnoringSpecialKey() {
+            return hasMessages(MSG_KEY_TYPED);
+        }
+
         // Working variables for the following methods.
         private boolean mIsOrientationChanging;
         private boolean mPendingSuccesiveImsCallback;
@@ -470,6 +499,7 @@
         mSubtypeSwitcher = SubtypeSwitcher.getInstance();
         mKeyboardSwitcher = KeyboardSwitcher.getInstance();
         mVibrator = VibratorCompatWrapper.getInstance(this);
+        mHandler.onCreate();
         DEBUG = LatinImeLogger.sDBG;
 
         final Resources res = getResources();
@@ -1246,15 +1276,16 @@
     // Implementation of {@link KeyboardActionListener}.
     @Override
     public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) {
-        long when = SystemClock.uptimeMillis();
+        final long when = SystemClock.uptimeMillis();
         if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) {
             mDeleteCount = 0;
         }
         mLastKeyTime = when;
-        KeyboardSwitcher switcher = mKeyboardSwitcher;
+        final KeyboardSwitcher switcher = mKeyboardSwitcher;
         final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
         final boolean lastStateOfJustReplacedDoubleSpace = mJustReplacedDoubleSpace;
         mJustReplacedDoubleSpace = false;
+        boolean shouldStartKeyTypedTimer = true;
         switch (primaryCode) {
         case Keyboard.CODE_DELETE:
             handleBackspace(lastStateOfJustReplacedDoubleSpace);
@@ -1264,13 +1295,17 @@
             break;
         case Keyboard.CODE_SHIFT:
             // Shift key is handled in onPress() when device has distinct multi-touch panel.
-            if (!distinctMultiTouch)
+            if (!distinctMultiTouch) {
                 switcher.toggleShift();
+            }
+            shouldStartKeyTypedTimer = false;
             break;
         case Keyboard.CODE_SWITCH_ALPHA_SYMBOL:
             // Symbol key is handled in onPress() when device has distinct multi-touch panel.
-            if (!distinctMultiTouch)
+            if (!distinctMultiTouch) {
                 switcher.changeKeyboardMode();
+            }
+            shouldStartKeyTypedTimer = false;
             break;
         case Keyboard.CODE_CANCEL:
             if (!isShowingOptionDialog()) {
@@ -1278,7 +1313,10 @@
             }
             break;
         case Keyboard.CODE_SETTINGS:
-            onSettingsKeyPressed();
+            if (!mHandler.isIgnoringSpecialKey()) {
+                onSettingsKeyPressed();
+            }
+            shouldStartKeyTypedTimer = false;
             break;
         case Keyboard.CODE_CAPSLOCK:
             switcher.toggleCapsLock();
@@ -1289,7 +1327,10 @@
             playKeyClick(primaryCode);
             break;
         case Keyboard.CODE_SHORTCUT:
-            mSubtypeSwitcher.switchToShortcutIME();
+            if (!mHandler.isIgnoringSpecialKey()) {
+                mSubtypeSwitcher.switchToShortcutIME();
+            }
+            shouldStartKeyTypedTimer = false;
             break;
         case Keyboard.CODE_TAB:
             handleTab();
@@ -1314,6 +1355,9 @@
         switcher.onKey(primaryCode);
         // Reset after any single keystroke
         mEnteredText = null;
+        if (shouldStartKeyTypedTimer) {
+            mHandler.startKeyTypedTimer();
+        }
     }
 
     @Override
@@ -1330,6 +1374,7 @@
         mKeyboardSwitcher.onKey(Keyboard.CODE_DUMMY);
         mJustAddedMagicSpace = false;
         mEnteredText = text;
+        mHandler.startKeyTypedTimer();
     }
 
     @Override
@@ -2100,8 +2145,12 @@
             // so that we need to re-create the keyboard input view here.
             setInputView(mKeyboardSwitcher.onCreateInputView());
         }
-        // Reload keyboard because the current language has been changed.
-        mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettingsValues);
+        // When the device locale is changed in SetupWizard etc., this method may get called via
+        // onConfigurationChanged before SoftInputWindow is shown.
+        if (mKeyboardSwitcher.getKeyboardView() != null) {
+            // Reload keyboard because the current language has been changed.
+            mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettingsValues);
+        }
         initSuggest();
         loadSettings();
     }
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index eeb0299..773efe7 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -102,13 +102,7 @@
 
     public static class Values {
         // From resources:
-        public final int mDelayBeforeFadeoutLanguageOnSpacebar;
-        public final int mDelayUpdateSuggestions;
         public final int mDelayUpdateOldSuggestions;
-        public final int mDelayUpdateShiftState;
-        public final int mDurationOfFadeoutLanguageOnSpacebar;
-        public final float mFinalFadeoutFactorOfLanguageOnSpacebar;
-        public final long mDoubleSpacesTurnIntoPeriodTimeout;
         public final String mWordSeparators;
         public final String mMagicSpaceStrippers;
         public final String mMagicSpaceSwappers;
@@ -147,20 +141,8 @@
             }
 
             // Get the resources
-            mDelayBeforeFadeoutLanguageOnSpacebar = res.getInteger(
-                    R.integer.config_delay_before_fadeout_language_on_spacebar);
-            mDelayUpdateSuggestions =
-                    res.getInteger(R.integer.config_delay_update_suggestions);
             mDelayUpdateOldSuggestions = res.getInteger(
                     R.integer.config_delay_update_old_suggestions);
-            mDelayUpdateShiftState =
-                    res.getInteger(R.integer.config_delay_update_shift_state);
-            mDurationOfFadeoutLanguageOnSpacebar = res.getInteger(
-                    R.integer.config_duration_of_fadeout_language_on_spacebar);
-            mFinalFadeoutFactorOfLanguageOnSpacebar = res.getInteger(
-                    R.integer.config_final_fadeout_percentage_of_language_on_spacebar) / 100.0f;
-            mDoubleSpacesTurnIntoPeriodTimeout = res.getInteger(
-                    R.integer.config_double_spaces_turn_into_period_timeout);
             mMagicSpaceStrippers = res.getString(R.string.magic_space_stripping_symbols);
             mMagicSpaceSwappers = res.getString(R.string.magic_space_swapping_symbols);
             String wordSeparators = mMagicSpaceStrippers + mMagicSpaceSwappers