Merge "Add SubtypeLocale class" into honeycomb
diff --git a/java/res/values-xlarge/config.xml b/java/res/values-xlarge/config.xml
index 56b9a16..410b5e1 100644
--- a/java/res/values-xlarge/config.xml
+++ b/java/res/values-xlarge/config.xml
@@ -28,6 +28,9 @@
     <bool name="config_digit_popup_characters_enabled">false</bool>
     <!-- Whether or not Popup on key press is enabled by default -->
     <bool name="config_default_popup_preview">false</bool>
+    <bool name="config_use_spacebar_language_switcher">false</bool>
+    <!-- The language is never displayed if == 0, always displayed if < 0 -->
+    <integer name="config_delay_before_fadeout_language_on_spacebar">1200</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 63af9a9..adfec4c 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -31,6 +31,10 @@
     <bool name="config_digit_popup_characters_enabled">true</bool>
     <!-- Whether or not Popup on key press is enabled by default -->
     <bool name="config_default_popup_preview">true</bool>
+    <bool name="config_use_spacebar_language_switcher">true</bool>
+    <!-- The language is never displayed if == 0, always displayed if < 0 -->
+    <integer name="config_delay_before_fadeout_language_on_spacebar">-1</integer>
+    <integer name="config_duration_of_fadeout_language_on_spacebar">50</integer>
     <integer name="config_delay_before_preview">0</integer>
     <integer name="config_delay_after_preview">10</integer>
     <integer name="config_preview_fadein_anim_time">0</integer>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 6d05012..6f0f2fb 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -22,7 +22,7 @@
     <string name="english_ime_name">Android keyboard</string>
     <!-- Title for Latin keyboard settings activity / dialog -->
     <string name="english_ime_settings">Android keyboard settings</string>
-    <!-- Title for Latin keyboard input options dialog -->
+    <!-- Title for Latin keyboard input options dialog [CHAR LIMIT=25] -->
     <string name="english_ime_input_options">Input options</string>
 
     <!-- Option to provide vibrate/haptic feedback on keypress -->
@@ -111,15 +111,15 @@
     <string name="voice_warning_locale_not_supported">Voice input is not currently supported for your language, but does work in English.</string>
 
     <!-- Message of the warning dialog that shows when a user initiates voice input for
-         the first time, or turns it on in settings. -->
+         the first time, or turns it on in settings. [CHAR LIMIT=200] -->
     <string name="voice_warning_may_not_understand">Voice input uses Google\'s speech recognition. <a href="http://m.google.com/privacy">The Mobile Privacy Policy</a> applies.</string>
 
     <!-- An additional part of the warning dialog for voice input that only shows when the user
-         actually initiates voice input, rather than just turning it on in settings. -->
+         actually initiates voice input, rather than just turning it on in settings. [CHAR LIMIT=200] -->
     <string name="voice_warning_how_to_turn_off">To turn off voice input, go to input method settings.</string>
 
     <!-- Message to show when user enables the voice input settings (which says
-        "Press the microphone button"). -->
+        "Press the microphone button"). [CHAR LIMIT=100] -->
     <string name="voice_hint_dialog_message">To use voice input, press the microphone button.</string>
 
     <!-- Short message to tell the user the system is ready for them to speak. -->
@@ -186,7 +186,7 @@
     <!-- On settings screen, voice input pop-up menu summary text to never show voice key [CHAR LIMIT=20] -->
     <string name="voice_input_modes_summary_off">Voice input is disabled</string>
 
-    <!-- Menu item for launching Input method picker -->
+    <!-- Title of the dialog for selecting input methods. [CHAR LIMIT=20] -->
     <string name="selectInputMethod">Select input method</string>
 
     <!-- Title for input language selection screen -->
@@ -204,12 +204,12 @@
     <string name="prefs_enable_log">Enable user feedback</string>
     <!-- Description for enabling to send user statistics to Google -->
     <string name="prefs_description_log">Help improve this input method editor by automatically sending usage statistics and crash reports to Google.</string>
-    <!-- Preferences item for enabling to correct suggestions by touching words you have typed -->
+    <!-- Preferences item for enabling to correct suggestions by touching words you have typed [CHAR LIMIT= 35] -->
     <string name="prefs_enable_recorrection">Touch to correct words</string>
-    <!-- The summary for the preferences item for enabling to correct suggestions by touching words you have typed -->
+    <!-- The summary for the preferences item for enabling to correct suggestions by touching words you have typed [CHAR LIMIT= 100] -->
     <string name="prefs_enable_recorrection_summary">Touch entered words to correct them, only when suggestions are visible</string>
 
-    <!-- Description for keyboard theme switcher -->
+    <!-- Title of the item to change the keyboard theme [CHAR LIMIT=20]-->
     <string name="keyboard_layout">Keyboard Theme</string>
 
     <!-- Description for Czech keyboard subtype [CHAR LIMIT=35] -->
diff --git a/java/res/xml-xlarge/kbd_key_styles.xml b/java/res/xml-xlarge/kbd_key_styles.xml
index c6b7858..efbad5b 100644
--- a/java/res/xml-xlarge/kbd_key_styles.xml
+++ b/java/res/xml-xlarge/kbd_key_styles.xml
@@ -57,7 +57,6 @@
             <key-style
                 latin:styleName="nonSpecialBackgroundSpaceKeyStyle"
                 latin:code="@integer/key_space"
-                latin:keyIcon="@drawable/sym_keyboard_space_holo"
                 latin:iconPreview="@drawable/sym_keyboard_feedback_space" />
             <key-style
                 latin:styleName="smileyKeyStyle"
@@ -102,12 +101,10 @@
             <key-style
                 latin:styleName="spaceKeyStyle"
                 latin:code="@integer/key_space"
-                latin:keyIcon="@drawable/sym_bkeyboard_space"
                 latin:iconPreview="@drawable/sym_keyboard_feedback_space" />
             <key-style
                 latin:styleName="nonSpecialBackgroundSpaceKeyStyle"
                 latin:code="@integer/key_space"
-                latin:keyIcon="@drawable/sym_bkeyboard_space"
                 latin:iconPreview="@drawable/sym_keyboard_feedback_space" />
             <key-style
                 latin:styleName="smileyKeyStyle"
diff --git a/java/res/xml-xlarge/kbd_number.xml b/java/res/xml-xlarge/kbd_number.xml
index 93bc136..c2cbb31 100644
--- a/java/res/xml-xlarge/kbd_number.xml
+++ b/java/res/xml-xlarge/kbd_number.xml
@@ -132,9 +132,15 @@
             latin:keyLabel="0" />
         <Key
             latin:keyLabel="#" />
-        <Key
-            latin:keyStyle="micKeyStyle"
-            latin:keyWidth="8.042%p" />
+        <switch>
+            <case
+                latin:voiceKeyEnabled="true"
+            >
+                <Key
+                    latin:keyStyle="micKeyStyle"
+                    latin:keyWidth="8.042%p" />
+            </case>
+        </switch>
         <!-- There is an empty area bellow the "Enter" key and right of the "#" key.  To ignore
              the touch event on the area, "#" is intentionally not marked as a right edge key. -->
     </Row>
diff --git a/java/res/xml-xlarge/kbd_numkey_styles.xml b/java/res/xml-xlarge/kbd_numkey_styles.xml
index 3c62cb0..e27db94 100644
--- a/java/res/xml-xlarge/kbd_numkey_styles.xml
+++ b/java/res/xml-xlarge/kbd_numkey_styles.xml
@@ -81,7 +81,6 @@
             <key-style
                 latin:styleName="numSpaceKeyStyle"
                 latin:code="@integer/key_space"
-                latin:keyIcon="@drawable/sym_keyboard_space_holo"
                 latin:iconPreview="@drawable/sym_keyboard_feedback_space" />
         </case>
         <case
@@ -143,7 +142,6 @@
             <key-style
                 latin:styleName="numSpaceKeyStyle"
                 latin:code="@integer/key_space"
-                latin:keyIcon="@drawable/sym_bkeyboard_space"
                 latin:iconPreview="@drawable/sym_keyboard_feedback_space" />
         </case>
     </switch>
diff --git a/java/res/xml-xlarge/kbd_phone.xml b/java/res/xml-xlarge/kbd_phone.xml
index 45c2983..c320ebb 100644
--- a/java/res/xml-xlarge/kbd_phone.xml
+++ b/java/res/xml-xlarge/kbd_phone.xml
@@ -140,9 +140,15 @@
             latin:keyStyle="num0KeyStyle" />
         <Key
             latin:keyStyle="numPoundKeyStyle" />
-        <Key
-            latin:keyStyle="micKeyStyle"
-            latin:keyWidth="8.042%p" />
+        <switch>
+            <case
+                latin:voiceKeyEnabled="true"
+            >
+                <Key
+                    latin:keyStyle="micKeyStyle"
+                    latin:keyWidth="8.042%p" />
+            </case>
+        </switch>
         <!-- There is an empty area bellow the "Enter" key and right of the "#" key.  To ignore
              the touch event on the area, "#" is intentionally not marked as a right edge key. -->
     </Row>
diff --git a/java/res/xml-xlarge/kbd_phone_symbols.xml b/java/res/xml-xlarge/kbd_phone_symbols.xml
index 891ceac..da15b5a 100644
--- a/java/res/xml-xlarge/kbd_phone_symbols.xml
+++ b/java/res/xml-xlarge/kbd_phone_symbols.xml
@@ -152,9 +152,15 @@
             latin:keyStyle="num0KeyStyle" />
         <Key
             latin:keyStyle="numPoundKeyStyle" />
-        <Key
-            latin:keyStyle="micKeyStyle"
-            latin:keyWidth="8.042%p" />
+        <switch>
+            <case
+                latin:voiceKeyEnabled="true"
+            >
+                <Key
+                    latin:keyStyle="micKeyStyle"
+                    latin:keyWidth="8.042%p" />
+            </case>
+        </switch>
         <!-- There is an empty area bellow the "Enter" key and right of the "#" key.  To ignore
              the touch event on the area, "#" is intentionally not marked as a right edge key. -->
     </Row>
diff --git a/java/res/xml-xlarge/kbd_qwerty_row4.xml b/java/res/xml-xlarge/kbd_qwerty_row4.xml
index e222a6b..98acfc1 100644
--- a/java/res/xml-xlarge/kbd_qwerty_row4.xml
+++ b/java/res/xml-xlarge/kbd_qwerty_row4.xml
@@ -114,7 +114,13 @@
                     latin:popupCharacters="_" />
             </default>
         </switch>
-        <Key
-            latin:keyStyle="micKeyStyle" />
+        <switch>
+            <case
+                latin:voiceKeyEnabled="true"
+            >
+                <Key
+                    latin:keyStyle="micKeyStyle" />
+            </case>
+        </switch>
     </Row>
 </merge>
diff --git a/java/res/xml-xlarge/kbd_symbols.xml b/java/res/xml-xlarge/kbd_symbols.xml
index 50b8e53..d804f79 100644
--- a/java/res/xml-xlarge/kbd_symbols.xml
+++ b/java/res/xml-xlarge/kbd_symbols.xml
@@ -162,7 +162,13 @@
             latin:popupCharacters="“,”,«,»,˝" />
         <Key
             latin:keyLabel="_" />
-        <Key
-            latin:keyStyle="micKeyStyle" />
+        <switch>
+            <case
+                latin:voiceKeyEnabled="true"
+            >
+                <Key
+                    latin:keyStyle="micKeyStyle" />
+            </case>
+        </switch>
     </Row>
 </Keyboard>
diff --git a/java/res/xml-xlarge/kbd_symbols_shift.xml b/java/res/xml-xlarge/kbd_symbols_shift.xml
index f586b1a..db33aaa 100644
--- a/java/res/xml-xlarge/kbd_symbols_shift.xml
+++ b/java/res/xml-xlarge/kbd_symbols_shift.xml
@@ -139,7 +139,13 @@
         <Key
             latin:keyStyle="spaceKeyStyle"
             latin:keyWidth="37.454%p" />
-        <Key
-            latin:keyStyle="micKeyStyle" />
+        <switch>
+            <case
+                latin:voiceKeyEnabled="true"
+            >
+                <Key
+                    latin:keyStyle="micKeyStyle" />
+            </case>
+        </switch>
     </Row>
 </Keyboard>
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 331c8db..25ef847 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -157,7 +157,14 @@
             boolean voiceButtonOnPrimary) {
         mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA;
         try {
+            if (mInputView == null) return;
+            final Keyboard oldKeyboard = mInputView.getKeyboard();
             loadKeyboardInternal(mode, imeOptions, voiceKeyEnabled, voiceButtonOnPrimary, false);
+            final Keyboard newKeyboard = mInputView.getKeyboard();
+            if (newKeyboard.isAlphaKeyboard() && (oldKeyboard == null
+                    || !newKeyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale))) {
+                mInputMethodService.mHandler.startDisplayLanguageOnSpacebar();
+            }
         } catch (RuntimeException e) {
             Log.w(TAG, e);
             LatinImeLogger.logOnException(mode + "," + imeOptions, e);
@@ -167,6 +174,11 @@
     private void loadKeyboardInternal(int mode, int imeOptions, boolean voiceButtonEnabled,
             boolean voiceButtonOnPrimary, boolean isSymbols) {
         if (mInputView == null) return;
+        final Keyboard oldKeyboard = mInputView.getKeyboard();
+        final KeyboardId id = getKeyboardId(mode, imeOptions, isSymbols);
+        if (oldKeyboard != null && oldKeyboard.mId.equals(id))
+            return;
+
         mInputView.setPreviewEnabled(mInputMethodService.getPopupOn());
 
         mMode = mode;
@@ -178,11 +190,8 @@
         mHasSettingsKey = getSettingsKeyMode(mPrefs, mInputMethodService);
         makeSymbolsKeyboardIds();
 
-        KeyboardId id = getKeyboardId(mode, imeOptions, isSymbols);
-        LatinKeyboard keyboard = getKeyboard(id);
-
         mCurrentId = id;
-        mInputView.setKeyboard(keyboard);
+        mInputView.setKeyboard(getKeyboard(id));
     }
 
     private LatinKeyboard getKeyboard(KeyboardId id) {
@@ -210,6 +219,10 @@
 
         keyboard.onAutoCorrectionStateChanged(mIsAutoCorrectionActive);
         keyboard.setShifted(false);
+        // If the cached keyboard had been switched to another keyboard while the language was
+        // displayed on its spacebar, it might have had arbitrary text fade factor. In such case,
+        // we should reset the text fade factor.
+        keyboard.setSpacebarTextFadeFactor(0.0f, null);
         return keyboard;
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index e7dd716..a952acf 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -912,9 +912,8 @@
         // We should re-draw popup preview when 1) we need to hide the preview, 2) we will show
         // the space key preview and 3) pointer moves off the space key to other letter key, we
         // should hide the preview of the previous key.
-        @SuppressWarnings("unused")
         final boolean hidePreviewOrShowSpaceKeyPreview = (tracker == null)
-                || (SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER
+                || (SubtypeSwitcher.getInstance().useSpacebarLanguageSwitcher()
                         && SubtypeSwitcher.getInstance().needsToDisplayLanguage()
                         && (tracker.isSpaceKey(keyIndex) || tracker.isSpaceKey(oldKeyIndex)));
         // If key changed and preview is on or the key is space (language switch is enabled)
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
index 77dde8d..db89340 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
@@ -24,6 +24,7 @@
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Paint.Align;
 import android.graphics.PorterDuff;
@@ -47,7 +48,9 @@
     private final Drawable mSpaceAutoCorrectionIndicator;
     private final Drawable mButtonArrowLeftIcon;
     private final Drawable mButtonArrowRightIcon;
-    private final int mSpaceBarTextShadowColor;
+    private final int mSpacebarTextColor;
+    private final int mSpacebarTextShadowColor;
+    private float mSpacebarTextFadeFactor = 0.0f;
     private final int[] mSpaceKeyIndexArray;
     private int mSpaceDragStartX;
     private int mSpaceDragLastDiff;
@@ -67,6 +70,7 @@
     private static final float SPACEBAR_POPUP_MIN_RATIO = 0.4f;
     // Height in space key the language name will be drawn. (proportional to space key height)
     public static final float SPACEBAR_LANGUAGE_BASELINE = 0.6f;
+    private static final float SPACEBAR_LANGUAGE_BASELINE_WITHOUT_ICON = 0.65f;
     // If the full language name needs to be smaller than this value to be drawn on space key,
     // its short language name will be used instead.
     private static final float MINIMUM_SCALE_OF_LANGUAGE_NAME = 0.8f;
@@ -80,11 +84,12 @@
         super(context, id.getXmlId(), id);
         final Resources res = context.getResources();
         mContext = context;
+        mSpacebarTextColor = res.getColor(R.color.latinkeyboard_bar_language_text);
         if (id.mColorScheme == KeyboardView.COLOR_SCHEME_BLACK) {
-            mSpaceBarTextShadowColor = res.getColor(
+            mSpacebarTextShadowColor = res.getColor(
                     R.color.latinkeyboard_bar_language_shadow_black);
         } else { // default color scheme is KeyboardView.COLOR_SCHEME_WHITE
-            mSpaceBarTextShadowColor = res.getColor(
+            mSpacebarTextShadowColor = res.getColor(
                     R.color.latinkeyboard_bar_language_shadow_white);
         }
         mSpaceAutoCorrectionIndicator = res.getDrawable(R.drawable.sym_keyboard_space_led);
@@ -96,25 +101,38 @@
         mSpaceKeyIndexArray = new int[] { indexOf(CODE_SPACE) };
     }
 
+    public void setSpacebarTextFadeFactor(float fadeFactor, LatinKeyboardView view) {
+        mSpacebarTextFadeFactor = fadeFactor;
+        updateSpacebarForLocale(false);
+        if (view != null)
+            view.invalidateKey(mSpaceKey);
+    }
+
+    private static int getSpacebarTextColor(int color, float fadeFactor) {
+        final int newColor = Color.argb((int)(Color.alpha(color) * fadeFactor),
+                Color.red(color), Color.green(color), Color.blue(color));
+        return newColor;
+    }
+
     /**
      * @return a key which should be invalidated.
      */
     public Key onAutoCorrectionStateChanged(boolean isAutoCorrection) {
-        updateSpaceBarForLocale(isAutoCorrection);
+        updateSpacebarForLocale(isAutoCorrection);
         return mSpaceKey;
     }
 
-    private void updateSpaceBarForLocale(boolean isAutoCorrection) {
+    private void updateSpacebarForLocale(boolean isAutoCorrection) {
         final Resources res = mContext.getResources();
         // If application locales are explicitly selected.
         if (SubtypeSwitcher.getInstance().needsToDisplayLanguage()) {
             mSpaceKey.setIcon(new BitmapDrawable(res,
-                    drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCorrection)));
+                    drawSpacebar(OPACITY_FULLY_OPAQUE, isAutoCorrection)));
         } else {
             // sym_keyboard_space_led can be shared with Black and White symbol themes.
             if (isAutoCorrection) {
                 mSpaceKey.setIcon(new BitmapDrawable(res,
-                        drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCorrection)));
+                        drawSpacebar(OPACITY_FULLY_OPAQUE, isAutoCorrection)));
             } else {
                 mSpaceKey.setIcon(mSpaceIcon);
             }
@@ -128,8 +146,8 @@
         return bounds.width();
     }
 
-    // Layout local language name and left and right arrow on space bar.
-    private static String layoutSpaceBar(Paint paint, Locale locale, Drawable lArrow,
+    // Layout local language name and left and right arrow on spacebar.
+    private static String layoutSpacebar(Paint paint, Locale locale, Drawable lArrow,
             Drawable rArrow, int width, int height, float origTextSize,
             boolean allowVariableTextSize) {
         final float arrowWidth = lArrow.getIntrinsicWidth();
@@ -138,7 +156,7 @@
         final Rect bounds = new Rect();
 
         // Estimate appropriate language name text size to fit in maxTextWidth.
-        String language = SubtypeSwitcher.getDisplayLanguage(locale);
+        String language = SubtypeSwitcher.getFullDisplayName(locale, true);
         int textWidth = getTextWidth(paint, language, origTextSize, bounds);
         // Assuming text width and text size are proportional to each other.
         float textSize = origTextSize * Math.min(maxTextWidth / textWidth, 1.0f);
@@ -171,8 +189,7 @@
         return language;
     }
 
-    @SuppressWarnings("unused")
-    private Bitmap drawSpaceBar(int opacity, boolean isAutoCorrection) {
+    private Bitmap drawSpacebar(int opacity, boolean isAutoCorrection) {
         final int width = mSpaceKey.mWidth;
         final int height = mSpaceIcon != null ? mSpaceIcon.getIntrinsicHeight() : mSpaceKey.mHeight;
         final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
@@ -202,21 +219,22 @@
             }
 
             final boolean allowVariableTextSize = true;
-            final String language = layoutSpaceBar(paint, subtypeSwitcher.getInputLocale(),
+            final String language = layoutSpacebar(paint, subtypeSwitcher.getInputLocale(),
                     mButtonArrowLeftIcon, mButtonArrowRightIcon, width, height,
                     getTextSizeFromTheme(textStyle, defaultTextSize),
                     allowVariableTextSize);
 
             // Draw language text with shadow
-            final float baseline = height * SPACEBAR_LANGUAGE_BASELINE;
+            final float baseline = height * (mSpaceIcon != null ? SPACEBAR_LANGUAGE_BASELINE
+                    : SPACEBAR_LANGUAGE_BASELINE_WITHOUT_ICON);
             final float descent = paint.descent();
-            paint.setColor(mSpaceBarTextShadowColor);
+            paint.setColor(getSpacebarTextColor(mSpacebarTextShadowColor, mSpacebarTextFadeFactor));
             canvas.drawText(language, width / 2, baseline - descent - 1, paint);
-            paint.setColor(res.getColor(R.color.latinkeyboard_bar_language_text));
+            paint.setColor(getSpacebarTextColor(mSpacebarTextColor, mSpacebarTextFadeFactor));
             canvas.drawText(language, width / 2, baseline - descent, paint);
 
             // Put arrows that are already layed out on either side of the text
-            if (SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER
+            if (SubtypeSwitcher.getInstance().useSpacebarLanguageSwitcher()
                     && subtypeSwitcher.getEnabledKeyboardLocaleCount() > 1) {
                 mButtonArrowLeftIcon.draw(canvas);
                 mButtonArrowRightIcon.draw(canvas);
@@ -291,7 +309,6 @@
      * switching input languages.
      */
     @Override
-    @SuppressWarnings("unused") // SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER is constant
     public boolean isInside(Key key, int pointX, int pointY) {
         int x = pointX;
         int y = pointY;
@@ -302,7 +319,7 @@
             if (code == CODE_DELETE) x -= key.mWidth / 6;
         } else if (code == CODE_SPACE) {
             y += LatinKeyboard.sSpacebarVerticalCorrection;
-            if (SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER
+            if (SubtypeSwitcher.getInstance().useSpacebarLanguageSwitcher()
                     && SubtypeSwitcher.getInstance().getEnabledKeyboardLocaleCount() > 1) {
                 if (mCurrentlyInSpace) {
                     int diff = x - mSpaceDragStartX;
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 51bfbf1..ef41cb6 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -85,6 +85,14 @@
         }
     }
 
+    public void setSpacebarTextFadeFactor(float fadeFactor, LatinKeyboard oldKeyboard) {
+        final LatinKeyboard currentKeyboard = getLatinKeyboard();
+        // We should not set text fade factor to the keyboard which does not display the language on
+        // its spacebar.
+        if (currentKeyboard != null && currentKeyboard == oldKeyboard)
+            currentKeyboard.setSpacebarTextFadeFactor(fadeFactor, this);
+    }
+
     @Override
     protected boolean onLongPress(Key key) {
         int primaryCode = key.mCode;
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index addc6c7..b93b07f 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -21,13 +21,11 @@
 import com.android.inputmethod.keyboard.KeyboardId;
 import com.android.inputmethod.keyboard.KeyboardSwitcher;
 import com.android.inputmethod.keyboard.KeyboardView;
+import com.android.inputmethod.keyboard.LatinKeyboard;
 import com.android.inputmethod.keyboard.LatinKeyboardView;
 import com.android.inputmethod.latin.Utils.RingCharBuffer;
 import com.android.inputmethod.voice.VoiceIMEConnector;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.app.AlertDialog;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -37,7 +35,6 @@
 import android.content.SharedPreferences;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.content.res.XmlResourceParser;
 import android.inputmethodservice.InputMethodService;
 import android.media.AudioManager;
 import android.os.Debug;
@@ -74,7 +71,6 @@
 import android.widget.LinearLayout;
 
 import java.io.FileDescriptor;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -156,6 +152,8 @@
     private boolean mAutoCap;
     private boolean mQuickFixes;
     private boolean mConfigSwipeDownDismissKeyboardEnabled;
+    private int mConfigDelayBeforeFadeoutLanguageOnSpacebar;
+    private int mConfigDurationOfFadeoutLanguageOnSpacebar;
 
     private int mCorrectionMode;
     private int mCommittedLength;
@@ -246,9 +244,13 @@
         private static final int MSG_UPDATE_OLD_SUGGESTIONS = 1;
         private static final int MSG_UPDATE_SHIFT_STATE = 2;
         private static final int MSG_VOICE_RESULTS = 3;
+        private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 4;
+        private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 5;
 
         @Override
         public void handleMessage(Message msg) {
+            final KeyboardSwitcher switcher = mKeyboardSwitcher;
+            final LatinKeyboardView inputView = switcher.getInputView();
             switch (msg.what) {
             case MSG_UPDATE_SUGGESTIONS:
                 updateSuggestions();
@@ -257,12 +259,21 @@
                 setOldSuggestions();
                 break;
             case MSG_UPDATE_SHIFT_STATE:
-                mKeyboardSwitcher.updateShiftState();
+                switcher.updateShiftState();
                 break;
             case MSG_VOICE_RESULTS:
                 mVoiceConnector.handleVoiceResults(preferCapitalization()
-                        || (mKeyboardSwitcher.isAlphabetMode()
-                                && mKeyboardSwitcher.isShiftedOrShiftLocked()));
+                        || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked()));
+                break;
+            case MSG_FADEOUT_LANGUAGE_ON_SPACEBAR:
+                if (inputView != null)
+                    inputView.setSpacebarTextFadeFactor(0.5f, (LatinKeyboard)msg.obj);
+                sendMessageDelayed(obtainMessage(MSG_DISMISS_LANGUAGE_ON_SPACEBAR, msg.obj),
+                        mConfigDurationOfFadeoutLanguageOnSpacebar);
+                break;
+            case MSG_DISMISS_LANGUAGE_ON_SPACEBAR:
+                if (inputView != null)
+                    inputView.setSpacebarTextFadeFactor(0.0f, (LatinKeyboard)msg.obj);
                 break;
             }
         }
@@ -302,6 +313,23 @@
         public void updateVoiceResults() {
             sendMessage(obtainMessage(MSG_VOICE_RESULTS));
         }
+
+        public void startDisplayLanguageOnSpacebar() {
+            removeMessages(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR);
+            removeMessages(MSG_DISMISS_LANGUAGE_ON_SPACEBAR);
+            final LatinKeyboardView inputView = mKeyboardSwitcher.getInputView();
+            if (inputView != null) {
+                final LatinKeyboard keyboard = inputView.getLatinKeyboard();
+                // The language is never displayed when the delay is zero.
+                if (mConfigDelayBeforeFadeoutLanguageOnSpacebar != 0)
+                    inputView.setSpacebarTextFadeFactor(1.0f, keyboard);
+                // The language is always displayed when the delay is negative.
+                if (mConfigDelayBeforeFadeoutLanguageOnSpacebar > 0) {
+                    sendMessageDelayed(obtainMessage(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR, keyboard),
+                            mConfigDelayBeforeFadeoutLanguageOnSpacebar);
+                }
+            }
+        }
     }
 
     @Override
@@ -324,6 +352,10 @@
                 res.getBoolean(R.bool.default_recorrection_enabled));
         mConfigSwipeDownDismissKeyboardEnabled = res.getBoolean(
                 R.bool.config_swipe_down_dismiss_keyboard_enabled);
+        mConfigDelayBeforeFadeoutLanguageOnSpacebar = res.getInteger(
+                R.integer.config_delay_before_fadeout_language_on_spacebar);
+        mConfigDurationOfFadeoutLanguageOnSpacebar = res.getInteger(
+                R.integer.config_duration_of_fadeout_language_on_spacebar);
 
         Utils.GCUtils.getInstance().reset();
         boolean tryGC = true;
@@ -406,23 +438,12 @@
 
     @Override
     public void onConfigurationChanged(Configuration conf) {
-        mSubtypeSwitcher.onConfigurationChanged(conf);
-        if (mSubtypeSwitcher.isKeyboardMode())
-            onKeyboardLanguageChanged();
-        updateAutoTextEnabled();
-
         // If orientation changed while predicting, commit the change
         if (conf.orientation != mOrientation) {
             InputConnection ic = getCurrentInputConnection();
             commitTyped(ic);
             if (ic != null) ic.finishComposingText(); // For voice input
             mOrientation = conf.orientation;
-            final int mode = mKeyboardSwitcher.getKeyboardMode();
-            final EditorInfo attribute = getCurrentInputEditorInfo();
-            final int imeOptions = (attribute != null) ? attribute.imeOptions : 0;
-            mKeyboardSwitcher.loadKeyboard(mode, imeOptions,
-                    mVoiceConnector.isVoiceButtonEnabled(),
-                    mVoiceConnector.isVoiceButtonOnPrimary());
         }
 
         mConfigurationChanging = true;
@@ -1822,7 +1843,7 @@
 
     // "reset" and "next" are used only for USE_SPACEBAR_LANGUAGE_SWITCHER.
     private void toggleLanguage(boolean reset, boolean next) {
-        if (SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER) {
+        if (mSubtypeSwitcher.useSpacebarLanguageSwitcher()) {
             mSubtypeSwitcher.toggleLanguage(reset, next);
         }
         // Reload keyboard because the current language has been changed.
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index f75e295..f04f3ef 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -41,10 +41,6 @@
 import java.util.Map;
 
 public class SubtypeSwitcher {
-    // TODO: This should be configurable by resource
-    // This flag indicates if we support language switching by swipe on space bar.
-    // We may or may not draw the current language on space bar regardless of this flag.
-    public static final boolean USE_SPACEBAR_LANGUAGE_SWITCHER = false;
     private static final boolean DBG = false;
     private static final String TAG = "SubtypeSwitcher";
 
@@ -63,6 +59,8 @@
             new ArrayList<InputMethodSubtype>();
     private final ArrayList<String> mEnabledLanguagesOfCurrentInputMethod = new ArrayList<String>();
 
+    private boolean mConfigUseSpacebarLanguageSwitcher;
+
     /*-----------------------------------------------------------*/
     // Variants which should be changed only by reload functions.
     private boolean mNeedsToDisplayLanguage;
@@ -84,10 +82,6 @@
     public static void init(LatinIME service, SharedPreferences prefs) {
         sInstance.mPrefs = prefs;
         sInstance.resetParams(service);
-        if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
-            sInstance.initLanguageSwitcher(service);
-        }
-
         sInstance.updateAllParameters();
 
         SubtypeLocale.init(service);
@@ -111,6 +105,10 @@
         mAllEnabledSubtypesOfCurrentInputMethod = null;
         // TODO: Voice input should be created here
         mVoiceInput = null;
+        mConfigUseSpacebarLanguageSwitcher = mResources.getBoolean(
+                R.bool.config_use_spacebar_language_switcher);
+        if (mConfigUseSpacebarLanguageSwitcher)
+            initLanguageSwitcher(service);
     }
 
     // Update all parameters stored in SubtypeSwitcher.
@@ -124,8 +122,8 @@
     // Update parameters which are changed outside LatinIME. This parameters affect UI so they
     // should be updated every time onStartInputview.
     public void updateParametersOnStartInputView() {
-        if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
-            updateForSpaceBarLanguageSwitch();
+        if (mConfigUseSpacebarLanguageSwitcher) {
+            updateForSpacebarLanguageSwitch();
         } else {
             updateEnabledSubtypes();
         }
@@ -309,19 +307,23 @@
     //////////////////////////////////
 
     public int getEnabledKeyboardLocaleCount() {
-        if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+        if (mConfigUseSpacebarLanguageSwitcher) {
             return mLanguageSwitcher.getLocaleCount();
         } else {
             return mEnabledKeyboardSubtypesOfCurrentInputMethod.size();
         }
     }
 
+    public boolean useSpacebarLanguageSwitcher() {
+        return mConfigUseSpacebarLanguageSwitcher;
+    }
+
     public boolean needsToDisplayLanguage() {
         return mNeedsToDisplayLanguage;
     }
 
     public Locale getInputLocale() {
-        if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+        if (mConfigUseSpacebarLanguageSwitcher) {
             return mLanguageSwitcher.getInputLocale();
         } else {
             return mInputLocale;
@@ -329,7 +331,7 @@
     }
 
     public String getInputLocaleStr() {
-        if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+        if (mConfigUseSpacebarLanguageSwitcher) {
             String inputLanguage = null;
             inputLanguage = mLanguageSwitcher.getInputLanguage();
             // Should return system locale if there is no Language available.
@@ -343,7 +345,7 @@
     }
 
     public String[] getEnabledLanguages() {
-        if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+        if (mConfigUseSpacebarLanguageSwitcher) {
             return mLanguageSwitcher.getEnabledLanguages();
         } else {
             return mEnabledLanguagesOfCurrentInputMethod.toArray(
@@ -352,7 +354,7 @@
     }
 
     public Locale getSystemLocale() {
-        if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+        if (mConfigUseSpacebarLanguageSwitcher) {
             return mLanguageSwitcher.getSystemLocale();
         } else {
             return mSystemLocale;
@@ -360,7 +362,7 @@
     }
 
     public boolean isSystemLanguageSameAsInputLanguage() {
-        if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+        if (mConfigUseSpacebarLanguageSwitcher) {
             return getSystemLocale().getLanguage().equalsIgnoreCase(
                     getInputLocaleStr().substring(0, 2));
         } else {
@@ -368,25 +370,8 @@
         }
     }
 
-    public void onConfigurationChanged(Configuration conf) {
-        final Locale systemLocale = conf.locale;
-        // If system configuration was changed, update all parameters.
-        if (!TextUtils.equals(systemLocale.toString(), mSystemLocale.toString())) {
-            if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
-                // If the system locale changes and is different from the saved
-                // locale (mSystemLocale), then reload the input locale list from the
-                // latin ime settings (shared prefs) and reset the input locale
-                // to the first one.
-                mLanguageSwitcher.loadLocales(mPrefs);
-                mLanguageSwitcher.setSystemLocale(systemLocale);
-            } else {
-                updateAllParameters();
-            }
-        }
-    }
-
     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
-        if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+        if (mConfigUseSpacebarLanguageSwitcher) {
             if (Settings.PREF_SELECTED_LANGUAGES.equals(key)) {
                 mLanguageSwitcher.loadLocales(sharedPreferences);
             }
@@ -434,12 +419,13 @@
     }
 
     private void triggerVoiceIME() {
+        if (!mService.isInputViewShown()) return;
         VoiceIMEConnector.getInstance().startListening(false,
                 KeyboardSwitcher.getInstance().getInputView().getWindowToken(), false);
     }
 
     //////////////////////////////////////
-    // SpaceBar Language Switch support //
+    // Spacebar Language Switch support //
     //////////////////////////////////////
 
     private LanguageSwitcher mLanguageSwitcher;
@@ -467,7 +453,7 @@
         return Character.toUpperCase(s.charAt(0)) + s.substring(1);
     }
 
-    private void updateForSpaceBarLanguageSwitch() {
+    private void updateForSpacebarLanguageSwitch() {
         // We need to update mNeedsToDisplayLanguage in onStartInputView because
         // getEnabledKeyboardLocaleCount could have been changed.
         mNeedsToDisplayLanguage = !(getEnabledKeyboardLocaleCount() <= 1
@@ -480,7 +466,7 @@
     }
 
     public String getNextInputLanguageName() {
-        if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+        if (mConfigUseSpacebarLanguageSwitcher) {
             return getDisplayLanguage(mLanguageSwitcher.getNextInputLocale());
         } else {
             return "";
@@ -488,7 +474,7 @@
     }
 
     public String getPreviousInputLanguageName() {
-        if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+        if (mConfigUseSpacebarLanguageSwitcher) {
             return getDisplayLanguage(mLanguageSwitcher.getPrevInputLocale());
         } else {
             return "";
@@ -525,13 +511,13 @@
     }
 
     public void loadSettings() {
-        if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+        if (mConfigUseSpacebarLanguageSwitcher) {
             mLanguageSwitcher.loadLocales(mPrefs);
         }
     }
 
     public void toggleLanguage(boolean reset, boolean next) {
-        if (USE_SPACEBAR_LANGUAGE_SWITCHER) {
+        if (mConfigUseSpacebarLanguageSwitcher) {
             if (reset) {
                 mLanguageSwitcher.reset();
             } else {