Merge "Auto generate various shift states alphabet keyboard automatically"
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 8d00f7a..a5bf6f6 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -60,16 +60,16 @@
         <attr name="keyHintLetterRatio" format="float" />
         <!-- Size of the text for hint label, in the proportion of key height. -->
         <attr name="keyHintLabelRatio" format="float" />
-        <!-- Size of the text for upper case letter, in the proportion of key height. -->
-        <attr name="keyUppercaseLetterRatio" format="float" />
+        <!-- Size of the text for shifted letter hint, in the proportion of key height. -->
+        <attr name="keyShiftedLetterHintRatio" format="float" />
         <!-- Horizontal padding of left/right aligned key label to the edge of the key. -->
         <attr name="keyLabelHorizontalPadding" format="dimension" />
         <!-- Top and right padding of hint letter to the edge of the key.-->
         <attr name="keyHintLetterPadding" format="dimension" />
         <!-- Bottom padding of popup hint letter "..." to the edge of the key.-->
         <attr name="keyPopupHintLetterPadding" format="dimension" />
-        <!-- Top and right padding of upper case letter to the edge of the key.-->
-        <attr name="keyUppercaseLetterPadding" format="dimension" />
+        <!-- Top and right padding of shifted letter hint to the edge of the key.-->
+        <attr name="keyShiftedLetterHintPadding" format="dimension" />
 
         <!-- Color to use for the label in a key. -->
         <attr name="keyTextColor" format="color" />
@@ -79,9 +79,9 @@
         <attr name="keyHintLetterColor" format="color" />
         <!-- Key hint label color -->
         <attr name="keyHintLabelColor" format="color" />
-        <!-- Upper case letter colors -->
-        <attr name="keyUppercaseLetterInactivatedColor" format="color" />
-        <attr name="keyUppercaseLetterActivatedColor" format="color" />
+        <!-- Shifted letter hint colors -->
+        <attr name="keyShiftedLetterHintInactivatedColor" format="color" />
+        <attr name="keyShiftedLetterHintActivatedColor" format="color" />
 
         <!-- Layout resource for key press feedback.-->
         <attr name="keyPreviewLayout" format="reference" />
@@ -240,7 +240,8 @@
             <enum name="normal" value="0" />
             <enum name="functional" value="1" />
             <enum name="action" value="2" />
-            <enum name="sticky" value="3" />
+            <enum name="stickyOff" value="3" />
+            <enum name="stickyOn" value="4" />
         </attr>
         <!-- The key action flags. -->
         <attr name="keyActionFlags" format="integer">
@@ -267,7 +268,7 @@
             <flag name="followKeyLetterRatio" value="0x80" />
             <flag name="followKeyHintLabelRatio" value="0x100" />
             <flag name="hasPopupHint" value="0x200" />
-            <flag name="hasUppercaseLetter" value="0x400" />
+            <flag name="hasShiftedLetterHint" value="0x400" />
             <flag name="hasHintLabel" value="0x800" />
             <flag name="withIconLeft" value="0x1000" />
             <flag name="withIconRight" value="0x2000" />
@@ -275,10 +276,9 @@
             <!-- If true, character case of code, altCode, moreKeys, keyOutputText, keyLabel,
                  or keyHintLabel will never be subject to change. -->
             <flag name="preserveCase" value="0x8000" />
-            <!-- If true, use keyTextInactivatedColor for the label -->
-            <flag name="inactivatedLabel" value="0x10000" />
-            <!-- If true, use keyUppercaseLetterInactivatedColor for the uppercase letter -->
-            <flag name="inactivatedUppercaseLetter" value="0x20000" />
+            <!-- If true, use keyShiftedLetterHintActivatedColor for the shifted letter hint and
+                 keyTextInactivatedColor for the primary key top label. -->
+            <flag name="shiftedLetterActivated" value="0x10000" />
         </attr>
         <!-- The icon to display on the key instead of the label. -->
         <attr name="keyIcon" format="enum">
@@ -407,7 +407,5 @@
             <enum name="number" value="9"  />
         </attr>
         <attr name="elementKeyboard" format="reference"/>
-        <attr name="elementAutoGenerate" format="boolean" />
-        <!-- TODO: Add setShifted and setShiftLocked attribute. -->
     </declare-styleable>
 </resources>
diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml
index 69637d7..f690782 100644
--- a/java/res/values/styles.xml
+++ b/java/res/values/styles.xml
@@ -39,18 +39,18 @@
         <item name="keyLabelRatio">@fraction/key_label_ratio</item>
         <item name="keyHintLetterRatio">@fraction/key_hint_letter_ratio</item>
         <item name="keyHintLabelRatio">@fraction/key_hint_label_ratio</item>
-        <item name="keyUppercaseLetterRatio">@fraction/key_uppercase_letter_ratio</item>
+        <item name="keyShiftedLetterHintRatio">@fraction/key_uppercase_letter_ratio</item>
         <item name="keyTextStyle">normal</item>
         <item name="keyTextColor">#FFFFFFFF</item>
         <item name="keyTextInactivatedColor">#FFFFFFFF</item>
         <item name="keyHintLetterColor">#80000000</item>
         <item name="keyHintLabelColor">#E0E0E4E5</item>
-        <item name="keyUppercaseLetterInactivatedColor">#66E0E4E5</item>
-        <item name="keyUppercaseLetterActivatedColor">#CCE0E4E5</item>
+        <item name="keyShiftedLetterHintInactivatedColor">#66E0E4E5</item>
+        <item name="keyShiftedLetterHintActivatedColor">#CCE0E4E5</item>
         <item name="keyLabelHorizontalPadding">@dimen/key_label_horizontal_padding</item>
         <item name="keyHintLetterPadding">@dimen/key_hint_letter_padding</item>
         <item name="keyPopupHintLetterPadding">@dimen/key_popup_hint_letter_padding</item>
-        <item name="keyUppercaseLetterPadding">@dimen/key_uppercase_letter_padding</item>
+        <item name="keyShiftedLetterHintPadding">@dimen/key_uppercase_letter_padding</item>
         <item name="keyPreviewLayout">@layout/key_preview</item>
         <item name="keyPreviewBackground">@drawable/keyboard_key_feedback</item>
         <item name="keyPreviewLeftBackground">@null</item>
@@ -181,8 +181,8 @@
         <item name="keyTextInactivatedColor">#FF808080</item>
         <item name="keyHintLetterColor">#80000000</item>
         <item name="keyHintLabelColor">#E0000000</item>
-        <item name="keyUppercaseLetterInactivatedColor">#66000000</item>
-        <item name="keyUppercaseLetterActivatedColor">#CC000000</item>
+        <item name="keyShiftedLetterHintInactivatedColor">#66000000</item>
+        <item name="keyShiftedLetterHintActivatedColor">#CC000000</item>
         <item name="shadowColor">#FFFFFFFF</item>
     </style>
     <style
@@ -298,8 +298,8 @@
         <item name="keyTextInactivatedColor">#66E0E4E5</item>
         <item name="keyHintLetterColor">#80000000</item>
         <item name="keyHintLabelColor">#A0FFFFFF</item>
-        <item name="keyUppercaseLetterInactivatedColor">#66E0E4E5</item>
-        <item name="keyUppercaseLetterActivatedColor">#FFFFFFFF</item>
+        <item name="keyShiftedLetterHintInactivatedColor">#66E0E4E5</item>
+        <item name="keyShiftedLetterHintActivatedColor">#FFFFFFFF</item>
         <item name="keyPreviewBackground">@drawable/keyboard_key_feedback_ics</item>
         <item name="keyPreviewLeftBackground">@drawable/keyboard_key_feedback_left_ics</item>
         <item name="keyPreviewRightBackground">@drawable/keyboard_key_feedback_right_ics</item>
diff --git a/java/res/xml-sw600dp/key_smiley.xml b/java/res/xml-sw600dp/key_smiley.xml
index ee23a81..3430d78 100644
--- a/java/res/xml-sw600dp/key_smiley.xml
+++ b/java/res/xml-sw600dp/key_smiley.xml
@@ -33,18 +33,18 @@
         >
             <Key
                 latin:keyLabel="-"
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel="_"
-                latin:moreKeys="_" />
+                latin:moreKeys="_"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </case>
         <case
             latin:imeAction="actionSearch"
         >
             <Key
                 latin:keyLabel=":"
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel="+"
-                latin:moreKeys="+" />
+                latin:moreKeys="+"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </case>
         <default>
             <Key
diff --git a/java/res/xml-sw600dp/key_styles_common.xml b/java/res/xml-sw600dp/key_styles_common.xml
index abba592..b554147 100644
--- a/java/res/xml-sw600dp/key_styles_common.xml
+++ b/java/res/xml-sw600dp/key_styles_common.xml
@@ -38,13 +38,51 @@
                 latin:backgroundType="functional" />
         </default>
     </switch>
+    <switch>
+        <case
+            latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+        >
+            <key-style
+                latin:styleName="hasShiftedLetterHintStyle"
+                latin:keyLabelFlags="hasShiftedLetterHint|shiftedLetterActivated" />
+        </case>
+        <default>
+            <key-style
+                latin:styleName="hasShiftedLetterHintStyle"
+                latin:keyLabelFlags="hasShiftedLetterHint" />
+        </default>
+    </switch>
     <!-- Functional key styles -->
-    <key-style
-        latin:styleName="shiftKeyStyle"
-        latin:code="@integer/key_shift"
-        latin:keyIcon="iconShiftKey"
-        latin:keyActionFlags="noKeyPreview"
-        latin:backgroundType="sticky" />
+    <switch>
+        <case
+            latin:keyboardSetElement="alphabetManualShifted|alphabetAutomaticShifted"
+        >
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKeyShifted"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOff" />
+        </case>
+        <case
+            latin:keyboardSetElement="alphabetShiftLocked|alphabetShiftLockShifted"
+        >
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKeyShifted"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOn" />
+        </case>
+        <default>
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKey"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOff" />
+        </default>
+    </switch>
     <key-style
         latin:styleName="deleteKeyStyle"
         latin:code="@integer/key_delete"
@@ -69,7 +107,7 @@
         latin:styleName="smileyKeyStyle"
         latin:keyLabel=":-)"
         latin:keyOutputText=":-) "
-        latin:keyLabelFlags="hasPopupHint"
+        latin:keyLabelFlags="hasPopupHint|preserveCase"
         latin:moreKeys="@string/more_keys_for_smiley"
         latin:maxMoreKeysColumn="5" />
     <key-style
@@ -95,30 +133,34 @@
         latin:styleName="toSymbolKeyStyle"
         latin:code="@integer/key_switch_alpha_symbol"
         latin:keyLabel="@string/label_to_symbol_key"
+        latin:keyLabelFlags="preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="toAlphaKeyStyle"
         latin:code="@integer/key_switch_alpha_symbol"
         latin:keyLabel="@string/label_to_alpha_key"
+        latin:keyLabelFlags="preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="toMoreSymbolKeyStyle"
         latin:code="@integer/key_shift"
         latin:keyLabel="@string/label_to_more_symbol_for_tablet_key"
+        latin:keyLabelFlags="preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="backFromMoreSymbolKeyStyle"
         latin:code="@integer/key_shift"
         latin:keyLabel="@string/label_to_symbol_key"
+        latin:keyLabelFlags="preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="comKeyStyle"
         latin:keyLabel="@string/keylabel_for_popular_domain"
-        latin:keyLabelFlags="fontNormal|hasPopupHint"
+        latin:keyLabelFlags="fontNormal|hasPopupHint|preserveCase"
         latin:keyOutputText="@string/keylabel_for_popular_domain"
         latin:moreKeys="@string/more_keys_for_popular_domain" />
 </merge>
diff --git a/java/res/xml-sw600dp/keys_apostrophe_dash.xml b/java/res/xml-sw600dp/keys_apostrophe_dash.xml
index 4eb82d2..a53c1e4 100644
--- a/java/res/xml-sw600dp/keys_apostrophe_dash.xml
+++ b/java/res/xml-sw600dp/keys_apostrophe_dash.xml
@@ -33,16 +33,16 @@
         >
             <Key
                 latin:keyLabel="/"
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel=":"
-                latin:moreKeys=":" />
+                latin:moreKeys=":"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </case>
         <default>
             <Key
                 latin:keyLabel="@string/keylabel_for_apostrophe"
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel="@string/keyhintlabel_for_apostrophe"
-                latin:moreKeys="@string/more_keys_for_apostrophe" />
+                latin:moreKeys="@string/more_keys_for_apostrophe"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </default>
     </switch>
     <switch>
@@ -55,9 +55,9 @@
         <default>
             <Key
                 latin:keyLabel="@string/keylabel_for_dash"
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel="@string/keyhintlabel_for_dash"
-                latin:moreKeys="@string/more_keys_for_dash" />
+                latin:moreKeys="@string/more_keys_for_dash"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </default>
     </switch>
 </merge>
diff --git a/java/res/xml-sw600dp/row_qwerty4.xml b/java/res/xml-sw600dp/row_qwerty4.xml
index bf6bcb1..b06508e 100644
--- a/java/res/xml-sw600dp/row_qwerty4.xml
+++ b/java/res/xml-sw600dp/row_qwerty4.xml
@@ -45,9 +45,9 @@
             <default>
                 <Key
                     latin:keyLabel="/"
-                    latin:keyLabelFlags="hasUppercaseLetter"
                     latin:keyHintLabel="\@"
-                    latin:moreKeys="\@" />
+                    latin:moreKeys="\@"
+                    latin:keyStyle="hasShiftedLetterHintStyle" />
             </default>
         </switch>
         <Key
diff --git a/java/res/xml-sw768dp/key_styles_common.xml b/java/res/xml-sw768dp/key_styles_common.xml
index 72a1a4c..0d2ac5d 100644
--- a/java/res/xml-sw768dp/key_styles_common.xml
+++ b/java/res/xml-sw768dp/key_styles_common.xml
@@ -21,12 +21,50 @@
 <merge
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
-    <key-style
-        latin:styleName="shiftKeyStyle"
-        latin:code="@integer/key_shift"
-        latin:keyIcon="iconShiftKey"
-        latin:keyActionFlags="noKeyPreview"
-        latin:backgroundType="sticky" />
+    <switch>
+        <case
+            latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+        >
+            <key-style
+                latin:styleName="hasShiftedLetterHintStyle"
+                latin:keyLabelFlags="hasShiftedLetterHint|shiftedLetterActivated" />
+        </case>
+        <default>
+            <key-style
+                latin:styleName="hasShiftedLetterHintStyle"
+                latin:keyLabelFlags="hasShiftedLetterHint" />
+        </default>
+    </switch>
+    <switch>
+        <case
+            latin:keyboardSetElement="alphabetManualShifted|alphabetAutomaticShifted"
+        >
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKeyShifted"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOff" />
+        </case>
+        <case
+            latin:keyboardSetElement="alphabetShiftLocked|alphabetShiftLockShifted"
+        >
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKeyShifted"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOn" />
+        </case>
+        <default>
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKey"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOff" />
+        </default>
+    </switch>
     <key-style
         latin:styleName="deleteKeyStyle"
         latin:code="@integer/key_delete"
@@ -51,7 +89,7 @@
         latin:styleName="smileyKeyStyle"
         latin:keyLabel=":-)"
         latin:keyOutputText=":-) "
-        latin:keyLabelFlags="hasPopupHint"
+        latin:keyLabelFlags="hasPopupHint|preserveCase"
         latin:moreKeys="@string/more_keys_for_smiley"
         latin:maxMoreKeysColumn="5" />
     <key-style
@@ -71,40 +109,40 @@
         latin:styleName="tabKeyStyle"
         latin:code="@integer/key_tab"
         latin:keyLabel="@string/label_tab_key"
-        latin:keyLabelFlags="fontNormal"
+        latin:keyLabelFlags="fontNormal|preserveCase"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="toSymbolKeyStyle"
         latin:code="@integer/key_switch_alpha_symbol"
         latin:keyLabel="@string/label_to_symbol_key"
-        latin:keyLabelFlags="fontNormal"
+        latin:keyLabelFlags="fontNormal|preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="toAlphaKeyStyle"
         latin:code="@integer/key_switch_alpha_symbol"
         latin:keyLabel="@string/label_to_alpha_key"
-        latin:keyLabelFlags="fontNormal"
+        latin:keyLabelFlags="fontNormal|preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="toMoreSymbolKeyStyle"
         latin:code="@integer/key_shift"
         latin:keyLabel="@string/label_to_more_symbol_for_tablet_key"
-        latin:keyLabelFlags="fontNormal"
+        latin:keyLabelFlags="fontNormal|preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="backFromMoreSymbolKeyStyle"
         latin:code="@integer/key_shift"
         latin:keyLabel="@string/label_to_symbol_key"
-        latin:keyLabelFlags="fontNormal"
+        latin:keyLabelFlags="fontNormal|preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="comKeyStyle"
         latin:keyLabel="@string/keylabel_for_popular_domain"
-        latin:keyLabelFlags="fontNormal|hasPopupHint"
+        latin:keyLabelFlags="fontNormal|hasPopupHint|preserveCase"
         latin:keyOutputText="@string/keylabel_for_popular_domain"
         latin:moreKeys="@string/more_keys_for_popular_domain" />
 </merge>
diff --git a/java/res/xml-sw768dp/keys_apostrophe_dash.xml b/java/res/xml-sw768dp/keys_apostrophe_dash.xml
index 4eb82d2..a53c1e4 100644
--- a/java/res/xml-sw768dp/keys_apostrophe_dash.xml
+++ b/java/res/xml-sw768dp/keys_apostrophe_dash.xml
@@ -33,16 +33,16 @@
         >
             <Key
                 latin:keyLabel="/"
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel=":"
-                latin:moreKeys=":" />
+                latin:moreKeys=":"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </case>
         <default>
             <Key
                 latin:keyLabel="@string/keylabel_for_apostrophe"
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel="@string/keyhintlabel_for_apostrophe"
-                latin:moreKeys="@string/more_keys_for_apostrophe" />
+                latin:moreKeys="@string/more_keys_for_apostrophe"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </default>
     </switch>
     <switch>
@@ -55,9 +55,9 @@
         <default>
             <Key
                 latin:keyLabel="@string/keylabel_for_dash"
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel="@string/keyhintlabel_for_dash"
-                latin:moreKeys="@string/more_keys_for_dash" />
+                latin:moreKeys="@string/more_keys_for_dash"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </default>
     </switch>
 </merge>
diff --git a/java/res/xml-sw768dp/row_qwerty4.xml b/java/res/xml-sw768dp/row_qwerty4.xml
index c3ba911..84c4a37 100644
--- a/java/res/xml-sw768dp/row_qwerty4.xml
+++ b/java/res/xml-sw768dp/row_qwerty4.xml
@@ -57,9 +57,9 @@
                     >
                         <Key
                             latin:keyLabel=":"
-                            latin:keyLabelFlags="hasUppercaseLetter"
                             latin:keyHintLabel="+"
-                            latin:moreKeys="+" />
+                            latin:moreKeys="+"
+                            latin:keyStyle="hasShiftedLetterHintStyle" />
                     </case>
                     <default>
                         <Key
@@ -76,9 +76,9 @@
                     <default>
                         <Key
                             latin:keyLabel="/"
-                            latin:keyLabelFlags="hasUppercaseLetter"
                             latin:keyHintLabel="\@"
-                            latin:moreKeys="\@" />
+                            latin:moreKeys="\@"
+                            latin:keyStyle="hasShiftedLetterHintStyle" />
                     </default>
                 </switch>
             </default>
diff --git a/java/res/xml-sw768dp/rows_azerty.xml b/java/res/xml-sw768dp/rows_azerty.xml
index 066778c..886ebec 100644
--- a/java/res/xml-sw768dp/rows_azerty.xml
+++ b/java/res/xml-sw768dp/rows_azerty.xml
@@ -124,7 +124,7 @@
             latin:moreKeys="@string/more_keys_for_n" />
         <Key
             latin:keyLabel="\'"
-            latin:keyLabelFlags="hasUppercaseLetter"
+            latin:keyLabelFlags="hasShiftedLetterHint"
             latin:keyHintLabel=":"
             latin:moreKeys=":" />
         <include
diff --git a/java/res/xml/key_styles_common.xml b/java/res/xml/key_styles_common.xml
index 7869d21..8d01e0f 100644
--- a/java/res/xml/key_styles_common.xml
+++ b/java/res/xml/key_styles_common.xml
@@ -62,12 +62,36 @@
         </default>
     </switch>
     <!-- Functional key styles -->
-    <key-style
-        latin:styleName="shiftKeyStyle"
-        latin:code="@integer/key_shift"
-        latin:keyIcon="iconShiftKey"
-        latin:keyActionFlags="noKeyPreview"
-        latin:backgroundType="sticky" />
+    <switch>
+        <case
+            latin:keyboardSetElement="alphabetManualShifted|alphabetAutomaticShifted"
+        >
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKeyShifted"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOff" />
+        </case>
+        <case
+            latin:keyboardSetElement="alphabetShiftLocked|alphabetShiftLockShifted"
+        >
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKeyShifted"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOn" />
+        </case>
+        <default>
+            <key-style
+                latin:styleName="shiftKeyStyle"
+                latin:code="@integer/key_shift"
+                latin:keyIcon="iconShiftKey"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="stickyOff" />
+        </default>
+    </switch>
     <key-style
         latin:styleName="deleteKeyStyle"
         latin:code="@integer/key_delete"
@@ -84,7 +108,7 @@
                 latin:styleName="returnKeyStyle"
                 latin:keyLabel=":-)"
                 latin:keyOutputText=":-) "
-                latin:keyLabelFlags="hasPopupHint"
+                latin:keyLabelFlags="hasPopupHint|preserveCase"
                 latin:moreKeys="@string/more_keys_for_smiley"
                 latin:maxMoreKeysColumn="5"
                 latin:backgroundType="functional" />
@@ -96,7 +120,7 @@
                 latin:styleName="returnKeyStyle"
                 latin:code="@integer/key_return"
                 latin:keyLabel="@string/label_go_key"
-                latin:keyLabelFlags="autoXScale"
+                latin:keyLabelFlags="autoXScale|preserveCase"
                 latin:keyActionFlags="noKeyPreview"
                 latin:backgroundType="action" />
         </case>
@@ -107,7 +131,7 @@
                 latin:styleName="returnKeyStyle"
                 latin:code="@integer/key_return"
                 latin:keyLabel="@string/label_next_key"
-                latin:keyLabelFlags="autoXScale"
+                latin:keyLabelFlags="autoXScale|preserveCase"
                 latin:keyActionFlags="noKeyPreview"
                 latin:backgroundType="action" />
         </case>
@@ -118,7 +142,7 @@
                 latin:styleName="returnKeyStyle"
                 latin:code="@integer/key_return"
                 latin:keyLabel="@string/label_done_key"
-                latin:keyLabelFlags="autoXScale"
+                latin:keyLabelFlags="autoXScale|preserveCase"
                 latin:keyActionFlags="noKeyPreview"
                 latin:backgroundType="action" />
         </case>
@@ -129,7 +153,7 @@
                 latin:styleName="returnKeyStyle"
                 latin:code="@integer/key_return"
                 latin:keyLabel="@string/label_send_key"
-                latin:keyLabelFlags="autoXScale"
+                latin:keyLabelFlags="autoXScale|preserveCase"
                 latin:keyActionFlags="noKeyPreview"
                 latin:backgroundType="action" />
         </case>
@@ -199,7 +223,7 @@
                 latin:code="@integer/key_switch_alpha_symbol"
                 latin:keyIcon="iconShortcutForLabel"
                 latin:keyLabel="@string/label_to_symbol_with_microphone_key"
-                latin:keyLabelFlags="withIconRight"
+                latin:keyLabelFlags="withIconRight|preserveCase"
                 latin:keyActionFlags="noKeyPreview"
                 latin:backgroundType="functional" />
         </case>
@@ -208,6 +232,7 @@
                 latin:styleName="toSymbolKeyStyle"
                 latin:code="@integer/key_switch_alpha_symbol"
                 latin:keyLabel="@string/label_to_symbol_key"
+                latin:keyLabelFlags="preserveCase"
                 latin:keyActionFlags="noKeyPreview"
                 latin:backgroundType="functional" />
         </default>
@@ -216,25 +241,28 @@
         latin:styleName="toAlphaKeyStyle"
         latin:code="@integer/key_switch_alpha_symbol"
         latin:keyLabel="@string/label_to_alpha_key"
+        latin:keyLabelFlags="preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="toMoreSymbolKeyStyle"
         latin:code="@integer/key_shift"
         latin:keyLabel="@string/label_to_more_symbol_key"
+        latin:keyLabelFlags="preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="backFromMoreSymbolKeyStyle"
         latin:code="@integer/key_shift"
         latin:keyLabel="@string/label_to_symbol_key"
+        latin:keyLabelFlags="preserveCase"
         latin:keyActionFlags="noKeyPreview"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="punctuationKeyStyle"
         latin:keyLabel="."
         latin:keyHintLabel="@string/keyhintlabel_for_punctuation"
-        latin:keyLabelFlags="hasPopupHint"
+        latin:keyLabelFlags="hasPopupHint|preserveCase"
         latin:moreKeys="@string/more_keys_for_punctuation"
         latin:maxMoreKeysColumn="@integer/mini_keyboard_column_for_punctuation"
         latin:backgroundType="functional" />
diff --git a/java/res/xml/keyboard_set.xml b/java/res/xml/keyboard_set.xml
index 27ef316..ebdd990 100644
--- a/java/res/xml/keyboard_set.xml
+++ b/java/res/xml/keyboard_set.xml
@@ -23,24 +23,7 @@
     latin:keyboardLocale="en_GB,en_US">
     <Element
         latin:elementName="alphabet"
-        latin:elementKeyboard="@xml/kbd_qwerty"
-        latin:elementAutoGenerate="true" />
-    <Element
-        latin:elementName="alphabetManualShifted"
-        latin:elementKeyboard="@xml/kbd_qwerty"
-        latin:elementAutoGenerate="true" />
-    <Element
-        latin:elementName="alphabetAutomaticShifted"
-        latin:elementKeyboard="@xml/kbd_qwerty"
-        latin:elementAutoGenerate="true" />
-    <Element
-        latin:elementName="alphabetShiftLocked"
-        latin:elementKeyboard="@xml/kbd_qwerty"
-        latin:elementAutoGenerate="true" />
-    <Element
-        latin:elementName="alphabetShiftLockShifted"
-        latin:elementKeyboard="@xml/kbd_qwerty"
-        latin:elementAutoGenerate="true" />
+        latin:elementKeyboard="@xml/kbd_qwerty" />
     <Element
         latin:elementName="symbols"
         latin:elementKeyboard="@xml/kbd_symbols" />
diff --git a/java/res/xml/keys_comma_period.xml b/java/res/xml/keys_comma_period.xml
index 97d9738..6db02b6 100644
--- a/java/res/xml/keys_comma_period.xml
+++ b/java/res/xml/keys_comma_period.xml
@@ -33,14 +33,14 @@
         <default>
             <Key
                 latin:keyLabel=","
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel="!"
-                latin:moreKeys="!" />
+                latin:moreKeys="!"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
             <Key
                 latin:keyLabel="."
-                latin:keyLabelFlags="hasUppercaseLetter"
                 latin:keyHintLabel="\?"
-                latin:moreKeys="\?" />
+                latin:moreKeys="\?"
+                latin:keyStyle="hasShiftedLetterHintStyle" />
         </default>
     </switch>
 </merge>
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index efaf58f..3b4149d 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -176,25 +176,6 @@
     }
 
     /**
-     * Returns the keycode for the specified key given the current keyboard
-     * state.
-     *
-     * @param keyboard The keyboard on which the key resides.
-     * @param key The key from which to obtain a key code.
-     * @return the key code for the specified key
-     */
-    private int getCorrectKeyCode(Keyboard keyboard, Key key) {
-        // If keyboard is in manual temporary upper case state and key has
-        // manual temporary uppercase letter as key hint letter, alternate
-        // character code should be sent.
-        if (keyboard.isManualTemporaryUpperCase() && key.hasUppercaseLetter()
-                && !TextUtils.isEmpty(key.mHintLabel)) {
-            return key.mHintLabel.charAt(0);
-        }
-        return key.mCode;
-    }
-
-    /**
      * Returns a localized character sequence describing what will happen when
      * the specified key is pressed based on its key code.
      * <p>
@@ -217,7 +198,7 @@
      */
     private CharSequence getDescriptionForKeyCode(Context context, Keyboard keyboard, Key key,
             boolean shouldObscure) {
-        final int code = getCorrectKeyCode(keyboard, key);
+        final int code = key.mCode;
 
         if (keyboard.isShiftLocked() && mShiftLockedKeyCodeMap.containsKey(code)) {
             return context.getString(mShiftLockedKeyCodeMap.get(code));
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index a2d3796..d4419ae 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -66,14 +66,13 @@
     private static final int LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO = 0x80;
     private static final int LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO = 0x100;
     private static final int LABEL_FLAGS_HAS_POPUP_HINT = 0x200;
-    private static final int LABEL_FLAGS_HAS_UPPERCASE_LETTER = 0x400;
+    private static final int LABEL_FLAGS_HAS_SHIFTED_LETTER_HINT = 0x400;
     private static final int LABEL_FLAGS_HAS_HINT_LABEL = 0x800;
     private static final int LABEL_FLAGS_WITH_ICON_LEFT = 0x1000;
     private static final int LABEL_FLAGS_WITH_ICON_RIGHT = 0x2000;
     private static final int LABEL_FLAGS_AUTO_X_SCALE = 0x4000;
     private static final int LABEL_FLAGS_PRESERVE_CASE = 0x8000;
-    private static final int LABEL_FLAGS_INACTIVATED_LABEL = 0x10000;
-    private static final int LABEL_FLAGS_INACTIVATED_UPPERCASE_LETTER = 0x20000;
+    private static final int LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED = 0x10000;
 
     /** Icon to display instead of a label. Icon takes precedence over a label */
     private final int mIconAttrId;
@@ -114,7 +113,8 @@
     public static final int BACKGROUND_TYPE_NORMAL = 0;
     public static final int BACKGROUND_TYPE_FUNCTIONAL = 1;
     public static final int BACKGROUND_TYPE_ACTION = 2;
-    public static final int BACKGROUND_TYPE_STICKY = 3;
+    public static final int BACKGROUND_TYPE_STICKY_OFF = 3;
+    public static final int BACKGROUND_TYPE_STICKY_ON = 4;
 
     private final int mActionFlags;
     private static final int ACTION_FLAGS_IS_REPEATABLE = 0x01;
@@ -125,8 +125,6 @@
 
     /** The current pressed state of this key */
     private boolean mPressed;
-    /** If this is a sticky key, is its highlight on? */
-    private boolean mHighlightOn;
     /** Key is enabled and responds on press */
     private boolean mEnabled = true;
 
@@ -303,31 +301,46 @@
                 keyAttr, R.styleable.Keyboard_Key_keyLabel), preserveCase, params.mId);
         mHintLabel = adjustCaseOfStringForKeyboardId(style.getString(
                 keyAttr, R.styleable.Keyboard_Key_keyHintLabel), preserveCase, params.mId);
-        mOutputText = adjustCaseOfStringForKeyboardId(style.getString(
+        String outputText = adjustCaseOfStringForKeyboardId(style.getString(
                 keyAttr, R.styleable.Keyboard_Key_keyOutputText), preserveCase, params.mId);
-        // Choose the first letter of the label as primary code if not
-        // specified.
-        final int code = adjustCaseOfCodeForKeyboardId(style.getInt(
-                keyAttr, R.styleable.Keyboard_Key_code, Keyboard.CODE_UNSPECIFIED), preserveCase,
-                params.mId);
-        if (code == Keyboard.CODE_UNSPECIFIED && mOutputText == null
+        final int code = style.getInt(
+                keyAttr, R.styleable.Keyboard_Key_code, Keyboard.CODE_UNSPECIFIED);
+        // Choose the first letter of the label as primary code if not specified.
+        if (code == Keyboard.CODE_UNSPECIFIED && TextUtils.isEmpty(outputText)
                 && !TextUtils.isEmpty(mLabel)) {
-            if (mLabel.length() != 1) {
-                Log.w(TAG, "Label is not a single letter: label=" + mLabel);
+            if (mLabel.codePointCount(0, mLabel.length()) == 1) {
+                final int activatedCode;
+                // Use the first letter of the hint label if shiftedLetterActivated flag is
+                // specified.
+                if (hasShiftedLetterHint() && isShiftedLetterActivated()
+                        && !TextUtils.isEmpty(mHintLabel)) {
+                    activatedCode = mHintLabel.codePointAt(0);
+                } else {
+                    activatedCode = mLabel.codePointAt(0);
+                }
+                mCode = getRtlParenthesisCode(activatedCode, params.mIsRtlKeyboard);
+            } else {
+                // In some locale and case, the character might be represented by multiple code
+                // points, such as upper case Eszett of German alphabet.
+                outputText = mLabel;
+                mCode = Keyboard.CODE_OUTPUT_TEXT;
             }
-            final int firstChar = mLabel.charAt(0);
-            mCode = getRtlParenthesisCode(firstChar, params.mIsRtlKeyboard);
-        } else if (code == Keyboard.CODE_UNSPECIFIED && mOutputText != null) {
+        } else if (code == Keyboard.CODE_UNSPECIFIED && outputText != null) {
             mCode = Keyboard.CODE_OUTPUT_TEXT;
         } else {
-            mCode = code;
+            mCode = adjustCaseOfCodeForKeyboardId(code, preserveCase, params.mId);
         }
+        mOutputText = outputText;
         mAltCode = adjustCaseOfCodeForKeyboardId(style.getInt(keyAttr,
                 R.styleable.Keyboard_Key_altCode, Keyboard.CODE_UNSPECIFIED), preserveCase,
                 params.mId);
         mHashCode = hashCode(this);
 
         keyAttr.recycle();
+
+        if (hasShiftedLetterHint() && TextUtils.isEmpty(mHintLabel)) {
+            Log.w(TAG, "hasShiftedLetterHint specified without keyHintLabel: " + this);
+        }
     }
 
     private static int adjustCaseOfCodeForKeyboardId(int code, boolean preserveCase,
@@ -335,7 +348,8 @@
         if (!Keyboard.isLetterCode(code) || preserveCase) return code;
         final String text = new String(new int[] { code } , 0, 1);
         final String casedText = adjustCaseOfStringForKeyboardId(text, preserveCase, id);
-        return casedText.codePointAt(0);
+        return casedText.codePointCount(0, casedText.length()) == 1
+                ? casedText.codePointAt(0) : Keyboard.CODE_UNSPECIFIED;
     }
 
     private static String adjustCaseOfStringForKeyboardId(String text, boolean preserveCase,
@@ -362,6 +376,7 @@
                 key.mLabel,
                 key.mHintLabel,
                 key.mIconAttrId,
+                key.mBackgroundType,
                 // Key can be distinguishable without the following members.
                 // key.mAltCode,
                 // key.mOutputText,
@@ -370,7 +385,6 @@
                 // key.mIcon,
                 // key.mDisabledIconAttrId,
                 // key.mPreviewIconAttrId,
-                // key.mBackgroundType,
                 // key.mHorizontalGap,
                 // key.mVerticalGap,
                 // key.mVisualInsetLeft,
@@ -388,7 +402,9 @@
                 && o.mHeight == mHeight
                 && o.mCode == mCode
                 && TextUtils.equals(o.mLabel, mLabel)
-                && TextUtils.equals(o.mHintLabel, mHintLabel);
+                && TextUtils.equals(o.mHintLabel, mHintLabel)
+                && o.mIconAttrId != mIconAttrId
+                && o.mBackgroundType != mBackgroundType;
     }
 
     @Override
@@ -401,6 +417,15 @@
         return o instanceof Key && equals((Key)o);
     }
 
+    @Override
+    public String toString() {
+        String top = Keyboard.printableCode(mCode);
+        if (mLabel != null && mLabel.length() != 1) {
+            top += "/\"" + mLabel + '"';
+        }
+        return String.format("%s %d,%d", top, mX, mY);
+    }
+
     public void markAsLeftEdge(Keyboard.Params params) {
         mHitBox.left = params.mHorizontalEdgesPadding;
     }
@@ -417,10 +442,6 @@
         mHitBox.bottom = params.mOccupiedHeight + params.mBottomPadding;
     }
 
-    public boolean isSticky() {
-        return mBackgroundType == BACKGROUND_TYPE_STICKY;
-    }
-
     public boolean isSpacer() {
         return false;
     }
@@ -486,8 +507,8 @@
         return (mLabelFlags & LABEL_FLAGS_HAS_POPUP_HINT) != 0;
     }
 
-    public boolean hasUppercaseLetter() {
-        return (mLabelFlags & LABEL_FLAGS_HAS_UPPERCASE_LETTER) != 0;
+    public boolean hasShiftedLetterHint() {
+        return (mLabelFlags & LABEL_FLAGS_HAS_SHIFTED_LETTER_HINT) != 0;
     }
 
     public boolean hasHintLabel() {
@@ -506,12 +527,8 @@
         return (mLabelFlags & LABEL_FLAGS_AUTO_X_SCALE) != 0;
     }
 
-    public boolean isInactivatedLabel() {
-        return (mLabelFlags & LABEL_FLAGS_INACTIVATED_LABEL) != 0;
-    }
-
-    public boolean isInactivatedUppercaseLetter() {
-        return (mLabelFlags & LABEL_FLAGS_INACTIVATED_UPPERCASE_LETTER) != 0;
+    public boolean isShiftedLetterActivated() {
+        return (mLabelFlags & LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) != 0;
     }
 
     // TODO: Get rid of this method.
@@ -542,10 +559,6 @@
         mPressed = false;
     }
 
-    public void setHighlightOn(boolean highlightOn) {
-        mHighlightOn = highlightOn;
-    }
-
     public boolean isEnabled() {
         return mEnabled;
     }
@@ -639,21 +652,17 @@
      * @see android.graphics.drawable.StateListDrawable#setState(int[])
      */
     public int[] getCurrentDrawableState() {
-        final boolean pressed = mPressed;
-
         switch (mBackgroundType) {
         case BACKGROUND_TYPE_FUNCTIONAL:
-            return pressed ? KEY_STATE_FUNCTIONAL_PRESSED : KEY_STATE_FUNCTIONAL_NORMAL;
+            return mPressed ? KEY_STATE_FUNCTIONAL_PRESSED : KEY_STATE_FUNCTIONAL_NORMAL;
         case BACKGROUND_TYPE_ACTION:
-            return pressed ? KEY_STATE_ACTIVE_PRESSED : KEY_STATE_ACTIVE_NORMAL;
-        case BACKGROUND_TYPE_STICKY:
-            if (mHighlightOn) {
-                return pressed ? KEY_STATE_PRESSED_HIGHLIGHT_ON : KEY_STATE_NORMAL_HIGHLIGHT_ON;
-            } else {
-                return pressed ? KEY_STATE_PRESSED_HIGHLIGHT_OFF : KEY_STATE_NORMAL_HIGHLIGHT_OFF;
-            }
+            return mPressed ? KEY_STATE_ACTIVE_PRESSED : KEY_STATE_ACTIVE_NORMAL;
+        case BACKGROUND_TYPE_STICKY_OFF:
+            return mPressed ? KEY_STATE_PRESSED_HIGHLIGHT_OFF : KEY_STATE_NORMAL_HIGHLIGHT_OFF;
+        case BACKGROUND_TYPE_STICKY_ON:
+            return mPressed ? KEY_STATE_PRESSED_HIGHLIGHT_ON : KEY_STATE_NORMAL_HIGHLIGHT_ON;
         default: /* BACKGROUND_TYPE_NORMAL */
-            return pressed ? KEY_STATE_PRESSED : KEY_STATE_NORMAL;
+            return mPressed ? KEY_STATE_PRESSED : KEY_STATE_NORMAL;
         }
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index dd88209..8832d8f 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -20,7 +20,6 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
-import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -31,7 +30,6 @@
 import com.android.inputmethod.compat.EditorInfoCompatUtils;
 import com.android.inputmethod.keyboard.internal.KeyStyles;
 import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
-import com.android.inputmethod.keyboard.internal.KeyboardShiftState;
 import com.android.inputmethod.latin.LatinImeLogger;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.XmlParseUtils;
@@ -130,16 +128,12 @@
     /** List of keys and icons in this keyboard */
     public final Set<Key> mKeys;
     public final Set<Key> mShiftKeys;
-    public final Set<Key> mShiftLockKeys;
     public final KeyboardIconsSet mIconsSet;
 
     private final Map<Integer, Key> mKeyCache = new HashMap<Integer, Key>();
 
     private final ProximityInfo mProximityInfo;
 
-    // TODO: Remove this variable.
-    private final KeyboardShiftState mShiftState = new KeyboardShiftState();
-
     public Keyboard(Params params) {
         mId = params.mId;
         mThemeId = params.mThemeId;
@@ -156,7 +150,6 @@
 
         mKeys = Collections.unmodifiableSet(params.mKeys);
         mShiftKeys = Collections.unmodifiableSet(params.mShiftKeys);
-        mShiftLockKeys = Collections.unmodifiableSet(params.mShiftLockKeys);
         mIconsSet = params.mIconsSet;
 
         mProximityInfo = new ProximityInfo(
@@ -188,70 +181,18 @@
     }
 
     // TODO: Remove this method.
-    boolean hasShiftLockKey() {
-        return !mShiftLockKeys.isEmpty();
-    }
-
-    // TODO: Remove this method.
-    void setShiftLocked(boolean newShiftLockState) {
-        for (final Key key : mShiftLockKeys) {
-            // To represent "shift locked" state. The highlight is handled by background image that
-            // might be a StateListDrawable.
-            key.setHighlightOn(newShiftLockState);
-            final int attrId = newShiftLockState
-                    ? R.styleable.Keyboard_iconShiftKeyShifted
-                    : R.styleable.Keyboard_iconShiftKey;
-            key.setIcon(mIconsSet.getIconByAttrId(attrId));
-        }
-        mShiftState.setShiftLocked(newShiftLockState);
-    }
-
-    // TODO: Move this method to KeyboardId.
     public boolean isShiftLocked() {
-        return mShiftState.isShiftLocked();
-    }
-
-    private void setShiftKeyGraphics(boolean newShiftState) {
-        if (mShiftState.isShiftLocked()) {
-            return;
-        }
-        for (final Key key : mShiftKeys) {
-            final int attrId = newShiftState
-                    ? R.styleable.Keyboard_iconShiftKeyShifted
-                    : R.styleable.Keyboard_iconShiftKey;
-            key.setIcon(mIconsSet.getIconByAttrId(attrId));
-        }
+        return mId.isAlphabetShiftLockedKeyboard();
     }
 
     // TODO: Remove this method.
-    void setShifted(boolean newShiftState) {
-        setShiftKeyGraphics(newShiftState);
-        mShiftState.setShifted(newShiftState);
-    }
-
-    // TODO: Move this method to KeyboardId.
     public boolean isShiftedOrShiftLocked() {
-        return mShiftState.isShiftedOrShiftLocked();
-    }
-
-    // TODO: Remove this method
-    void setAutomaticTemporaryUpperCase() {
-        setShiftKeyGraphics(true);
-        mShiftState.setAutomaticTemporaryUpperCase();
-    }
-
-    // TODO: Move this method to KeyboardId.
-    public boolean isManualTemporaryUpperCase() {
-        return mShiftState.isManualTemporaryUpperCase();
+        return mId.isAlphabetShiftedOrShiftLockedKeyboard();
     }
 
     // TODO: Remove this method.
-    public String adjustLabelCase(String label) {
-        if (mId.isAlphabetKeyboard() && isShiftedOrShiftLocked() && !TextUtils.isEmpty(label)
-                && label.length() < 3 && Character.isLowerCase(label.charAt(0))) {
-            return label.toUpperCase(mId.mLocale);
-        }
-        return label;
+    public boolean isManualShifted() {
+        return mId.isAlphabetManualShiftedKeyboard();
     }
 
     public static boolean isLetterCode(int code) {
@@ -291,7 +232,6 @@
 
         public final Set<Key> mKeys = new HashSet<Key>();
         public final Set<Key> mShiftKeys = new HashSet<Key>();
-        public final Set<Key> mShiftLockKeys = new HashSet<Key>();
         public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet();
 
         public KeyboardSet.KeysCache mKeysCache;
@@ -360,7 +300,6 @@
         protected void clearKeys() {
             mKeys.clear();
             mShiftKeys.clear();
-            mShiftLockKeys.clear();
             clearHistogram();
         }
 
@@ -370,9 +309,6 @@
             updateHistogram(key);
             if (key.mCode == Keyboard.CODE_SHIFT) {
                 mShiftKeys.add(key);
-                if (key.isSticky()) {
-                    mShiftLockKeys.add(key);
-                }
             }
         }
 
@@ -437,6 +373,8 @@
         case CODE_DELETE: return "delete";
         case CODE_SHORTCUT: return "shortcut";
         case CODE_UNSPECIFIED: return "unspec";
+        case CODE_TAB: return "tab";
+        case CODE_ENTER: return "enter";
         default:
             if (code <= 0) Log.w(TAG, "Unknown non-positive key code=" + code);
             if (code < CODE_SPACE) return String.format("'\\u%02x'", code);
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
index 8db8c94..997b952 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
@@ -124,6 +124,22 @@
         return mElementId < ELEMENT_SYMBOLS;
     }
 
+    // This should be aligned with {@link KeyboardShiftState#isShiftLocked}.
+    public boolean isAlphabetShiftLockedKeyboard() {
+        return mElementId == ELEMENT_ALPHABET_SHIFT_LOCKED
+                || mElementId == ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED;
+    }
+
+    // This should be aligned with {@link KeyboardShiftState#isShiftedOrShiftLocked}.
+    public boolean isAlphabetShiftedOrShiftLockedKeyboard() {
+        return isAlphabetKeyboard() && mElementId != ELEMENT_ALPHABET;
+    }
+
+    // This should be aligned with {@link KeyboardShiftState#isManualShifted}.
+    public boolean isAlphabetManualShiftedKeyboard() {
+        return mElementId != ELEMENT_ALPHABET_MANUAL_SHIFTED;
+    }
+
     public boolean isSymbolsKeyboard() {
         return mElementId == ELEMENT_SYMBOLS || mElementId == ELEMENT_SYMBOLS_SHIFTED;
     }
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
index ae5e4e8..0aed506 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
@@ -77,17 +77,6 @@
         }
     }
 
-    static class KeyboardElement {
-        final int mElementId;
-        final int mLayoutId;
-        final boolean mAutoGenerate;
-        KeyboardElement(int elementId, int layoutId, boolean autoGenerate) {
-            mElementId = elementId;
-            mLayoutId = layoutId;
-            mAutoGenerate = autoGenerate;
-        }
-    }
-
     static class Params {
         int mMode;
         int mInputType;
@@ -100,8 +89,9 @@
         Locale mLocale;
         int mOrientation;
         int mWidth;
-        final Map<Integer, KeyboardElement> mElementKeyboards =
-                new HashMap<Integer, KeyboardElement>();
+        // KeyboardSet element id to keyboard layout XML id map.
+        final Map<Integer, Integer> mKeyboardSetElementIdToXmlIdMap =
+                new HashMap<Integer, Integer>();
         Params() {}
     }
 
@@ -117,41 +107,38 @@
         mParams = params;
     }
 
+    // TODO: Remove this method, use {@link #getKeyboard} directly.
     public Keyboard getMainKeyboard() {
-        return getKeyboard(false, false, false);
+        return getKeyboard(KeyboardId.ELEMENT_ALPHABET);
     }
 
-    public Keyboard getSymbolsKeyboard() {
-        return getKeyboard(true, false, false);
-    }
+    public Keyboard getKeyboard(int baseKeyboardSetElementId) {
+        final int keyboardSetElementId;
+        switch (mParams.mMode) {
+        case KeyboardId.MODE_PHONE:
+            keyboardSetElementId =
+                    (baseKeyboardSetElementId == KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED)
+                    ? KeyboardId.ELEMENT_PHONE_SHIFTED : KeyboardId.ELEMENT_PHONE;
+            break;
+        case KeyboardId.MODE_NUMBER:
+            keyboardSetElementId = KeyboardId.ELEMENT_NUMBER;
+            break;
+        default:
+            keyboardSetElementId = baseKeyboardSetElementId;
+            break;
+        }
 
-    public Keyboard getSymbolsShiftedKeyboard() {
-        final Keyboard keyboard = getKeyboard(true, false, true);
-        // TODO: Remove this logic once we introduce initial keyboard shift state attribute.
-        // Symbol shift keyboard may have a shift key that has a caps lock style indicator (a.k.a.
-        // sticky shift key). To show or dismiss the indicator, we need to call setShiftLocked()
-        // that takes care of the current keyboard having such shift key or not.
-        keyboard.setShiftLocked(keyboard.hasShiftLockKey());
+        Integer keyboardXmlId = mParams.mKeyboardSetElementIdToXmlIdMap.get(keyboardSetElementId);
+        if (keyboardXmlId == null) {
+            keyboardXmlId = mParams.mKeyboardSetElementIdToXmlIdMap.get(
+                    KeyboardId.ELEMENT_ALPHABET);
+        }
+        final KeyboardId id = getKeyboardId(keyboardSetElementId);
+        final Keyboard keyboard = getKeyboard(mContext, keyboardXmlId, id);
         return keyboard;
     }
 
-    private Keyboard getKeyboard(boolean isSymbols, boolean isShiftLock, boolean isShift) {
-        final int elementId = KeyboardSet.getElementId(
-                mParams.mMode, isSymbols, isShiftLock, isShift);
-        final KeyboardElement keyboardElement = mParams.mElementKeyboards.get(elementId);
-        // TODO: If keyboardElement.mAutoGenerate is true, the keyboard will be auto generated
-        // based on keyboardElement.mKayoutId Keyboard XML definition.
-        final KeyboardId id = KeyboardSet.getKeyboardId(elementId, isSymbols, mParams);
-        final Keyboard keyboard = getKeyboard(mContext, keyboardElement, id);
-        return keyboard;
-    }
-
-    public KeyboardId getMainKeyboardId() {
-        final int elementId = KeyboardSet.getElementId(mParams.mMode, false, false, false);
-        return KeyboardSet.getKeyboardId(elementId, false, mParams);
-    }
-
-    private Keyboard getKeyboard(Context context, KeyboardElement element, KeyboardId id) {
+    private Keyboard getKeyboard(Context context, int keyboardXmlId, KeyboardId id) {
         final Resources res = context.getResources();
         final SoftReference<Keyboard> ref = sKeyboardCache.get(id);
         Keyboard keyboard = (ref == null) ? null : ref.get();
@@ -160,10 +147,10 @@
             try {
                 final Keyboard.Builder<Keyboard.Params> builder =
                         new Keyboard.Builder<Keyboard.Params>(context, new Keyboard.Params());
-                if (element.mAutoGenerate) {
+                if (id.isAlphabetKeyboard()) {
                     builder.setAutoGenerate(mKeysCache);
                 }
-                builder.load(element.mLayoutId, id);
+                builder.load(keyboardXmlId, id);
                 builder.setTouchPositionCorrectionEnabled(mParams.mTouchPositionCorrectionEnabled);
                 keyboard = builder.build();
             } finally {
@@ -179,36 +166,23 @@
             Log.d(TAG, "keyboard cache size=" + sKeyboardCache.size() + ": HIT  id=" + id);
         }
 
-        // TODO: Remove setShiftLocked and setShift calls.
-        keyboard.setShiftLocked(false);
-        keyboard.setShifted(false);
         return keyboard;
     }
 
-    private static int getElementId(int mode, boolean isSymbols, boolean isShiftLock,
-            boolean isShift) {
-        switch (mode) {
-        case KeyboardId.MODE_PHONE:
-            return (isSymbols && isShift)
-                    ? KeyboardId.ELEMENT_PHONE_SHIFTED : KeyboardId.ELEMENT_PHONE;
-        case KeyboardId.MODE_NUMBER:
-            return KeyboardId.ELEMENT_NUMBER;
-        default:
-            if (isSymbols) {
-                return isShift
-                        ? KeyboardId.ELEMENT_SYMBOLS_SHIFTED : KeyboardId.ELEMENT_SYMBOLS;
-            }
-            // TODO: Consult isShiftLock and isShift to determine the element.
-            return KeyboardId.ELEMENT_ALPHABET;
-        }
-    }
-
-    private static KeyboardId getKeyboardId(int elementId, boolean isSymbols, Params params) {
+    // TODO: Make this method private.
+    // Note: The keyboard for each locale, shift state, and mode are represented as KeyboardSet
+    // element id that is a key in keyboard_set.xml.  Also that file specifies which XML layout
+    // should be used for each keyboard.  The KeyboardId is an internal key for Keyboard object.
+    public KeyboardId getKeyboardId(int keyboardSetElementId) {
+        final Params params = mParams;
+        final boolean isSymbols = (keyboardSetElementId == KeyboardId.ELEMENT_SYMBOLS
+                || keyboardSetElementId == KeyboardId.ELEMENT_SYMBOLS_SHIFTED);
         final boolean hasShortcutKey = params.mVoiceKeyEnabled
                 && (isSymbols != params.mVoiceKeyOnMain);
-        return new KeyboardId(elementId, params.mLocale, params.mOrientation, params.mWidth,
-                params.mMode, params.mInputType, params.mImeOptions, params.mSettingsKeyEnabled,
-                params.mNoSettingsKey, params.mVoiceKeyEnabled, hasShortcutKey);
+        return new KeyboardId(keyboardSetElementId, params.mLocale, params.mOrientation,
+                params.mWidth, params.mMode, params.mInputType, params.mImeOptions,
+                params.mSettingsKeyEnabled, params.mNoSettingsKey, params.mVoiceKeyEnabled,
+                hasShortcutKey);
     }
 
     public static class Builder {
@@ -345,10 +319,7 @@
                         R.styleable.KeyboardSet_Element_elementName, 0);
                 final int elementKeyboard = a.getResourceId(
                         R.styleable.KeyboardSet_Element_elementKeyboard, 0);
-                final boolean elementAutoGenerate = a.getBoolean(
-                        R.styleable.KeyboardSet_Element_elementAutoGenerate, false);
-                mParams.mElementKeyboards.put(elementName, new KeyboardElement(
-                        elementName, elementKeyboard, elementAutoGenerate));
+                mParams.mKeyboardSetElementIdToXmlIdMap.put(elementName, elementKeyboard);
             } finally {
                 a.recycle();
             }
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 5a59cc1..17ad45d 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -135,24 +135,19 @@
                 settingsValues.isVoiceKeyEnabled(editorInfo),
                 settingsValues.isVoiceKeyOnMain());
         mKeyboardSet = builder.build();
-        final KeyboardId mainKeyboardId = mKeyboardSet.getMainKeyboardId();
         try {
             mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols));
         } catch (RuntimeException e) {
-            Log.w(TAG, "loading keyboard failed: " + mainKeyboardId, e);
-            LatinImeLogger.logOnException(mainKeyboardId.toString(), e);
+            Log.w(TAG, "loading keyboard failed: " + mKeyboardSet.getKeyboardId(
+                    KeyboardId.ELEMENT_ALPHABET), e);
+            LatinImeLogger.logOnException(mKeyboardSet.getKeyboardId(
+                    KeyboardId.ELEMENT_ALPHABET).toString(), e);
             return;
         }
-        // TODO: Should get rid of this special case handling for Phone Number layouts once we
-        // have separate layouts with unique KeyboardIds for alphabet and alphabet-shifted
-        // respectively.
-        if (mainKeyboardId.isPhoneKeyboard()) {
-            mState.setSymbolsKeyboard();
-        }
     }
 
     public void saveKeyboardState() {
-        if (isKeyboardAvailable()) {
+        if (getKeyboard() != null) {
             mState.onSaveKeyboardState();
         }
     }
@@ -184,31 +179,23 @@
         mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged);
     }
 
+    // TODO: Remove this method.
     public boolean isAlphabetMode() {
         final Keyboard keyboard = getKeyboard();
         return keyboard != null && keyboard.mId.isAlphabetKeyboard();
     }
 
+    // TODO: Remove this method.
     public boolean isInputViewShown() {
         return mCurrentInputView != null && mCurrentInputView.isShown();
     }
 
+    // TODO: Remove this method.
     public boolean isShiftedOrShiftLocked() {
         final Keyboard keyboard = getKeyboard();
         return keyboard != null && keyboard.isShiftedOrShiftLocked();
     }
 
-    public boolean isManualTemporaryUpperCase() {
-        final Keyboard keyboard = getKeyboard();
-        return keyboard != null && keyboard.isManualTemporaryUpperCase();
-    }
-
-    public boolean isKeyboardAvailable() {
-        if (mKeyboardView != null)
-            return mKeyboardView.getKeyboard() != null;
-        return false;
-    }
-
     public Keyboard getKeyboard() {
         if (mKeyboardView != null) {
             return mKeyboardView.getKeyboard();
@@ -235,91 +222,46 @@
         mState.onCancelInput(isSinglePointer());
     }
 
-    // TODO: Remove these constants.
-    private static final int ALPHABET_UNSHIFTED = 0;
-    private static final int ALPHABET_MANUAL_SHIFTED = 1;
-    private static final int ALPHABET_AUTOMATIC_SHIFTED = 2;
-    private static final int ALPHABET_SHIFT_LOCKED = 3;
-    private static final int ALPHABET_SHIFT_LOCK_SHIFTED = 4;
-
-    // TODO: Remove this method.
-    private void updateAlphabetKeyboardShiftState(int shiftMode) {
-        mInputMethodService.mHandler.cancelUpdateShiftState();
-        Keyboard keyboard = getKeyboard();
-        if (keyboard == null)
-            return;
-        switch (shiftMode) {
-        case ALPHABET_UNSHIFTED:
-            keyboard.setShifted(false);
-            break;
-        case ALPHABET_MANUAL_SHIFTED:
-            keyboard.setShifted(true);
-            break;
-        case ALPHABET_AUTOMATIC_SHIFTED:
-            keyboard.setAutomaticTemporaryUpperCase();
-            break;
-        case ALPHABET_SHIFT_LOCKED:
-            keyboard.setShiftLocked(true);
-            break;
-        case ALPHABET_SHIFT_LOCK_SHIFTED:
-            keyboard.setShiftLocked(true);
-            keyboard.setShifted(true);
-            break;
-        }
-        mKeyboardView.invalidateAllKeys();
-        if (shiftMode != ALPHABET_SHIFT_LOCKED) {
-            // To be able to turn off caps lock by "double tap" on shift key, we should ignore
-            // the second tap of the "double tap" from now for a while because we just have
-            // already turned off caps lock above.
-            mKeyboardView.startIgnoringDoubleTap();
-        }
-    }
-
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setAlphabetKeyboard() {
-        setKeyboard(mKeyboardSet.getMainKeyboard());
-        updateAlphabetKeyboardShiftState(ALPHABET_UNSHIFTED);
+        setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setAlphabetManualShiftedKeyboard() {
-        setKeyboard(mKeyboardSet.getMainKeyboard());
-        updateAlphabetKeyboardShiftState(ALPHABET_MANUAL_SHIFTED);
+        setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setAlphabetAutomaticShiftedKeyboard() {
-        setKeyboard(mKeyboardSet.getMainKeyboard());
-        updateAlphabetKeyboardShiftState(ALPHABET_AUTOMATIC_SHIFTED);
+        setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setAlphabetShiftLockedKeyboard() {
-        setKeyboard(mKeyboardSet.getMainKeyboard());
-        updateAlphabetKeyboardShiftState(ALPHABET_SHIFT_LOCKED);
+        setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setAlphabetShiftLockShiftedKeyboard() {
-        setKeyboard(mKeyboardSet.getMainKeyboard());
-        updateAlphabetKeyboardShiftState(ALPHABET_SHIFT_LOCK_SHIFTED);
+        setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setSymbolsKeyboard() {
-        setKeyboard(mKeyboardSet.getSymbolsKeyboard());
+        setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setSymbolsShiftedKeyboard() {
-        setKeyboard(mKeyboardSet.getSymbolsShiftedKeyboard());
+        setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS_SHIFTED));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index d977327..2cbd132 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -53,12 +53,12 @@
  * @attr ref R.styleable#KeyboardView_keyLargeLetterRatio
  * @attr ref R.styleable#KeyboardView_keyLabelRatio
  * @attr ref R.styleable#KeyboardView_keyHintLetterRatio
- * @attr ref R.styleable#KeyboardView_keyUppercaseLetterRatio
+ * @attr ref R.styleable#KeyboardView_keyShiftedLetterHintRatio
  * @attr ref R.styleable#KeyboardView_keyHintLabelRatio
  * @attr ref R.styleable#KeyboardView_keyLabelHorizontalPadding
  * @attr ref R.styleable#KeyboardView_keyHintLetterPadding
  * @attr ref R.styleable#KeyboardView_keyPopupHintLetterPadding
- * @attr ref R.styleable#KeyboardView_keyUppercaseLetterPadding
+ * @attr ref R.styleable#KeyboardView_keyShiftedLetterHintPadding
  * @attr ref R.styleable#KeyboardView_keyTextStyle
  * @attr ref R.styleable#KeyboardView_keyPreviewLayout
  * @attr ref R.styleable#KeyboardView_keyPreviewTextRatio
@@ -68,8 +68,8 @@
  * @attr ref R.styleable#KeyboardView_keyTextColorDisabled
  * @attr ref R.styleable#KeyboardView_keyHintLetterColor
  * @attr ref R.styleable#KeyboardView_keyHintLabelColor
- * @attr ref R.styleable#KeyboardView_keyUppercaseLetterInactivatedColor
- * @attr ref R.styleable#KeyboardView_keyUppercaseLetterActivatedColor
+ * @attr ref R.styleable#KeyboardView_keyShiftedLetterHintInactivatedColor
+ * @attr ref R.styleable#KeyboardView_keyShiftedLetterHintActivatedColor
  * @attr ref R.styleable#KeyboardView_shadowColor
  * @attr ref R.styleable#KeyboardView_shadowRadius
  */
@@ -175,20 +175,20 @@
         public final float mKeyLabelHorizontalPadding;
         public final float mKeyHintLetterPadding;
         public final float mKeyPopupHintLetterPadding;
-        public final float mKeyUppercaseLetterPadding;
+        public final float mKeyShiftedLetterHintPadding;
         public final int mShadowColor;
         public final float mShadowRadius;
         public final Drawable mKeyBackground;
         public final int mKeyHintLetterColor;
         public final int mKeyHintLabelColor;
-        public final int mKeyUppercaseLetterInactivatedColor;
-        public final int mKeyUppercaseLetterActivatedColor;
+        public final int mKeyShiftedLetterHintInactivatedColor;
+        public final int mKeyShiftedLetterHintActivatedColor;
 
         private final float mKeyLetterRatio;
         private final float mKeyLargeLetterRatio;
         private final float mKeyLabelRatio;
         private final float mKeyHintLetterRatio;
-        private final float mKeyUppercaseLetterRatio;
+        private final float mKeyShiftedLetterHintRatio;
         private final float mKeyHintLabelRatio;
         private static final float UNDEFINED_RATIO = -1.0f;
 
@@ -197,7 +197,7 @@
         public int mKeyLargeLetterSize;
         public int mKeyLabelSize;
         public int mKeyHintLetterSize;
-        public int mKeyUppercaseLetterSize;
+        public int mKeyShiftedLetterHintSize;
         public int mKeyHintLabelSize;
 
         public KeyDrawParams(TypedArray a) {
@@ -216,8 +216,8 @@
             }
             mKeyLargeLetterRatio = getRatio(a, R.styleable.KeyboardView_keyLargeLetterRatio);
             mKeyHintLetterRatio = getRatio(a, R.styleable.KeyboardView_keyHintLetterRatio);
-            mKeyUppercaseLetterRatio = getRatio(a,
-                    R.styleable.KeyboardView_keyUppercaseLetterRatio);
+            mKeyShiftedLetterHintRatio = getRatio(a,
+                    R.styleable.KeyboardView_keyShiftedLetterHintRatio);
             mKeyHintLabelRatio = getRatio(a, R.styleable.KeyboardView_keyHintLabelRatio);
             mKeyLabelHorizontalPadding = a.getDimension(
                     R.styleable.KeyboardView_keyLabelHorizontalPadding, 0);
@@ -225,17 +225,17 @@
                     R.styleable.KeyboardView_keyHintLetterPadding, 0);
             mKeyPopupHintLetterPadding = a.getDimension(
                     R.styleable.KeyboardView_keyPopupHintLetterPadding, 0);
-            mKeyUppercaseLetterPadding = a.getDimension(
-                    R.styleable.KeyboardView_keyUppercaseLetterPadding, 0);
+            mKeyShiftedLetterHintPadding = a.getDimension(
+                    R.styleable.KeyboardView_keyShiftedLetterHintPadding, 0);
             mKeyTextColor = a.getColor(R.styleable.KeyboardView_keyTextColor, 0xFF000000);
             mKeyTextInactivatedColor = a.getColor(
                     R.styleable.KeyboardView_keyTextInactivatedColor, 0xFF000000);
             mKeyHintLetterColor = a.getColor(R.styleable.KeyboardView_keyHintLetterColor, 0);
             mKeyHintLabelColor = a.getColor(R.styleable.KeyboardView_keyHintLabelColor, 0);
-            mKeyUppercaseLetterInactivatedColor = a.getColor(
-                    R.styleable.KeyboardView_keyUppercaseLetterInactivatedColor, 0);
-            mKeyUppercaseLetterActivatedColor = a.getColor(
-                    R.styleable.KeyboardView_keyUppercaseLetterActivatedColor, 0);
+            mKeyShiftedLetterHintInactivatedColor = a.getColor(
+                    R.styleable.KeyboardView_keyShiftedLetterHintInactivatedColor, 0);
+            mKeyShiftedLetterHintActivatedColor = a.getColor(
+                    R.styleable.KeyboardView_keyShiftedLetterHintActivatedColor, 0);
             mKeyTextStyle = Typeface.defaultFromStyle(
                     a.getInt(R.styleable.KeyboardView_keyTextStyle, Typeface.NORMAL));
             mShadowColor = a.getColor(R.styleable.KeyboardView_shadowColor, 0);
@@ -251,7 +251,7 @@
                 mKeyLabelSize = (int)(keyHeight * mKeyLabelRatio);
             mKeyLargeLetterSize = (int)(keyHeight * mKeyLargeLetterRatio);
             mKeyHintLetterSize = (int)(keyHeight * mKeyHintLetterRatio);
-            mKeyUppercaseLetterSize = (int)(keyHeight * mKeyUppercaseLetterRatio);
+            mKeyShiftedLetterHintSize = (int)(keyHeight * mKeyShiftedLetterHintRatio);
             mKeyHintLabelSize = (int)(keyHeight * mKeyHintLabelRatio);
         }
     }
@@ -527,8 +527,7 @@
         final Drawable icon = key.getIcon(mKeyboard.mIconsSet);
         float positionX = centerX;
         if (key.mLabel != null) {
-            // Switch the character to uppercase if shift is pressed
-            final String label = mKeyboard.adjustLabelCase(key.mLabel);
+            final String label = key.mLabel;
             // For characters, use large font. For labels like "Done", use smaller font.
             paint.setTypeface(key.selectTypeface(params.mKeyTextStyle));
             final int labelSize = key.selectTextSize(params.mKeyLetterSize,
@@ -571,14 +570,8 @@
                         Math.min(1.0f, (keyWidth * MAX_LABEL_RATIO) / getLabelWidth(label, paint)));
             }
 
-            // TODO: Remove this first if-clause.
-            if (key.hasUppercaseLetter() && mKeyboard.isManualTemporaryUpperCase()) {
-                paint.setColor(params.mKeyTextInactivatedColor);
-            } else if (key.isInactivatedLabel()) {
-                paint.setColor(params.mKeyTextInactivatedColor);
-            } else {
-                paint.setColor(params.mKeyTextColor);
-            }
+            paint.setColor(key.isShiftedLetterActivated()
+                    ? params.mKeyTextInactivatedColor : params.mKeyTextColor);
             if (key.isEnabled()) {
                 // Set a drop shadow for the text
                 paint.setShadowLayer(params.mShadowRadius, 0, 0, params.mShadowColor);
@@ -620,16 +613,11 @@
                 hintColor = params.mKeyHintLabelColor;
                 hintSize = params.mKeyHintLabelSize;
                 paint.setTypeface(Typeface.DEFAULT);
-            } else if (key.hasUppercaseLetter()) {
-                // TODO: Remove this first if-clause.
-                if (mKeyboard.isManualTemporaryUpperCase()) {
-                    hintColor = params.mKeyUppercaseLetterActivatedColor;
-                } else if (!key.isInactivatedUppercaseLetter()) {
-                    hintColor = params.mKeyUppercaseLetterActivatedColor;
-                } else {
-                    hintColor = params.mKeyUppercaseLetterInactivatedColor;
-                }
-                hintSize = params.mKeyUppercaseLetterSize;
+            } else if (key.hasShiftedLetterHint()) {
+                hintColor = key.isShiftedLetterActivated()
+                        ? params.mKeyShiftedLetterHintActivatedColor
+                        : params.mKeyShiftedLetterHintInactivatedColor;
+                hintSize = params.mKeyShiftedLetterHintSize;
             } else { // key.hasHintLetter()
                 hintColor = params.mKeyHintLetterColor;
                 hintSize = params.mKeyHintLetterSize;
@@ -644,9 +632,9 @@
                 hintX = positionX + getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) * 2;
                 hintY = centerY + getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint) / 2;
                 paint.setTextAlign(Align.LEFT);
-            } else if (key.hasUppercaseLetter()) {
+            } else if (key.hasShiftedLetterHint()) {
                 // The hint label is placed at top-right corner of the key. Used mainly on tablet.
-                hintX = keyWidth - params.mKeyUppercaseLetterPadding
+                hintX = keyWidth - params.mKeyShiftedLetterHintPadding
                         - getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2;
                 hintY = -paint.ascent();
                 paint.setTextAlign(Align.CENTER);
@@ -870,7 +858,7 @@
                 previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, params.mPreviewTextSize);
                 previewText.setTypeface(params.mKeyTextStyle);
             }
-            previewText.setText(mKeyboard.adjustLabelCase(key.mLabel));
+            previewText.setText(key.mLabel);
         } else {
             final Drawable previewIcon = mKeyboard.mIconsSet.getIconByAttrId(
                     key.mPreviewIconAttrId);
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 7e8a718..056aa25 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -548,7 +548,6 @@
         mMoreKeysPanelPointerTrackerId = tracker.mPointerId;
 
         final Keyboard keyboard = getKeyboard();
-        moreKeysPanel.setShifted(keyboard.isShiftedOrShiftLocked());
         final int pointX = (mConfigShowMiniKeyboardAtTouchedPoint) ? tracker.getLastX()
                 : parentKey.mX + parentKey.mWidth / 2;
         final int pointY = parentKey.mY - keyboard.mVerticalGap;
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java
index 1f9ed5e..72d5b68 100644
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java
@@ -131,13 +131,6 @@
     }
 
     @Override
-    public void setShifted(boolean shifted) {
-        final Keyboard keyboard = getKeyboard();
-        keyboard.setShifted(shifted);
-        invalidateAllKeys();
-    }
-
-    @Override
     public void showMoreKeysPanel(View parentView, Controller controller, int pointX, int pointY,
             PopupWindow window, KeyboardActionListener listener) {
         mController = controller;
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java b/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java
index a3ff372..f9a196d 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java
@@ -24,9 +24,6 @@
         public boolean dismissMoreKeysPanel();
     }
 
-    // TODO: Remove this method.
-    public void setShifted(boolean shifted);
-
     /**
      * Show more keys panel.
      *
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index a75b8f9..4dac347 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -705,7 +705,7 @@
             if (sParams.mLongPressSpaceKeyTimeout > 0) {
                 mTimerProxy.startLongPressTimer(sParams.mLongPressSpaceKeyTimeout, this);
             }
-        } else if (key.hasUppercaseLetter() && mKeyboard.isManualTemporaryUpperCase()) {
+        } else if (key.hasShiftedLetterHint() && mKeyboard.isManualShifted()) {
             // 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.
             return;
@@ -727,13 +727,6 @@
         final int[] codes = mKeyDetector.newCodeArray();
         mKeyDetector.getKeyAndNearbyCodes(x, y, codes);
 
-        // If keyboard is in manual temporary upper case state and key has manual temporary
-        // uppercase letter as key hint letter, alternate character code should be sent.
-        if (mKeyboard.isManualTemporaryUpperCase() && key.hasUppercaseLetter()) {
-            code = key.mHintLabel.charAt(0);
-            codes[0] = code;
-        }
-
         // Swap the first and second values in the codes array if the primary code is not the
         // first value but the second value in the array. This happens when key debouncing is
         // in effect.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java
similarity index 76%
rename from java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java
rename to java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java
index 4608e22..5712df1 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java
@@ -18,27 +18,27 @@
 
 import android.util.Log;
 
-public class KeyboardShiftState {
-    private static final String TAG = KeyboardShiftState.class.getSimpleName();
+public class AlphabetShiftState {
+    private static final String TAG = AlphabetShiftState.class.getSimpleName();
     private static final boolean DEBUG = false;
 
-    private static final int NORMAL = 0;
+    private static final int UNSHIFTED = 0;
     private static final int MANUAL_SHIFTED = 1;
     private static final int MANUAL_SHIFTED_FROM_AUTO = 2;
-    private static final int AUTO_SHIFTED = 3;
+    private static final int AUTOMATIC_SHIFTED = 3;
     private static final int SHIFT_LOCKED = 4;
     private static final int SHIFT_LOCK_SHIFTED = 5;
 
-    private int mState = NORMAL;
+    private int mState = UNSHIFTED;
 
     public void setShifted(boolean newShiftState) {
         final int oldState = mState;
         if (newShiftState) {
             switch (oldState) {
-            case NORMAL:
+            case UNSHIFTED:
                 mState = MANUAL_SHIFTED;
                 break;
-            case AUTO_SHIFTED:
+            case AUTOMATIC_SHIFTED:
                 mState = MANUAL_SHIFTED_FROM_AUTO;
                 break;
             case SHIFT_LOCKED:
@@ -49,8 +49,8 @@
             switch (oldState) {
             case MANUAL_SHIFTED:
             case MANUAL_SHIFTED_FROM_AUTO:
-            case AUTO_SHIFTED:
-                mState = NORMAL;
+            case AUTOMATIC_SHIFTED:
+                mState = UNSHIFTED;
                 break;
             case SHIFT_LOCK_SHIFTED:
                 mState = SHIFT_LOCKED;
@@ -65,30 +65,30 @@
         final int oldState = mState;
         if (newShiftLockState) {
             switch (oldState) {
-            case NORMAL:
+            case UNSHIFTED:
             case MANUAL_SHIFTED:
             case MANUAL_SHIFTED_FROM_AUTO:
-            case AUTO_SHIFTED:
+            case AUTOMATIC_SHIFTED:
                 mState = SHIFT_LOCKED;
                 break;
             }
         } else {
-            mState = NORMAL;
+            mState = UNSHIFTED;
         }
         if (DEBUG)
             Log.d(TAG, "setShiftLocked(" + newShiftLockState + "): " + toString(oldState)
                     + " > " + this);
     }
 
-    public void setAutomaticTemporaryUpperCase() {
+    public void setAutomaticShifted() {
         final int oldState = mState;
-        mState = AUTO_SHIFTED;
+        mState = AUTOMATIC_SHIFTED;
         if (DEBUG)
-            Log.d(TAG, "setAutomaticTemporaryUpperCase: " + toString(oldState) + " > " + this);
+            Log.d(TAG, "setAutomaticShifted: " + toString(oldState) + " > " + this);
     }
 
     public boolean isShiftedOrShiftLocked() {
-        return mState != NORMAL;
+        return mState != UNSHIFTED;
     }
 
     public boolean isShiftLocked() {
@@ -99,16 +99,16 @@
         return mState == SHIFT_LOCK_SHIFTED;
     }
 
-    public boolean isAutomaticTemporaryUpperCase() {
-        return mState == AUTO_SHIFTED;
+    public boolean isAutomaticShifted() {
+        return mState == AUTOMATIC_SHIFTED;
     }
 
-    public boolean isManualTemporaryUpperCase() {
+    public boolean isManualShifted() {
         return mState == MANUAL_SHIFTED || mState == MANUAL_SHIFTED_FROM_AUTO
                 || mState == SHIFT_LOCK_SHIFTED;
     }
 
-    public boolean isManualTemporaryUpperCaseFromAuto() {
+    public boolean isManualShiftedFromAutomaticShifted() {
         return mState == MANUAL_SHIFTED_FROM_AUTO;
     }
 
@@ -119,13 +119,13 @@
 
     private static String toString(int state) {
         switch (state) {
-        case NORMAL: return "NORMAL";
+        case UNSHIFTED: return "UNSHIFTED";
         case MANUAL_SHIFTED: return "MANUAL_SHIFTED";
         case MANUAL_SHIFTED_FROM_AUTO: return "MANUAL_SHIFTED_FROM_AUTO";
-        case AUTO_SHIFTED: return "AUTO_SHIFTED";
+        case AUTOMATIC_SHIFTED: return "AUTOMATIC_SHIFTED";
         case SHIFT_LOCKED: return "SHIFT_LOCKED";
         case SHIFT_LOCK_SHIFTED: return "SHIFT_LOCK_SHIFTED";
-        default: return "UKNOWN";
+        default: return "UNKNOWN";
         }
     }
 }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 5542bd3..4af4e3c 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -70,7 +70,7 @@
     private String mLayoutSwitchBackSymbols;
 
     private boolean mIsAlphabetMode;
-    private KeyboardShiftState mAlphabetShiftState = new KeyboardShiftState();
+    private AlphabetShiftState mAlphabetShiftState = new AlphabetShiftState();
     private boolean mIsSymbolShifted;
     private boolean mPrevMainKeyboardWasShiftLocked;
     private boolean mPrevSymbolsKeyboardWasShifted;
@@ -167,16 +167,16 @@
         }
         if (!mIsAlphabetMode) return;
         final int prevShiftMode;
-        if (mAlphabetShiftState.isAutomaticTemporaryUpperCase()) {
+        if (mAlphabetShiftState.isAutomaticShifted()) {
             prevShiftMode = AUTOMATIC_SHIFT;
-        } else if (mAlphabetShiftState.isManualTemporaryUpperCase()) {
+        } else if (mAlphabetShiftState.isManualShifted()) {
             prevShiftMode = MANUAL_SHIFT;
         } else {
             prevShiftMode = UNSHIFT;
         }
         switch (shiftMode) {
         case AUTOMATIC_SHIFT:
-            mAlphabetShiftState.setAutomaticTemporaryUpperCase();
+            mAlphabetShiftState.setAutomaticShifted();
             if (shiftMode != prevShiftMode) {
                 mSwitchActions.setAlphabetAutomaticShiftedKeyboard();
             }
@@ -353,7 +353,7 @@
                 // caps lock state and mark as if shift key pressed while normal state.
                 setShifted(SHIFT_LOCK_SHIFTED);
                 mShiftKeyState.onPress();
-            } else if (mAlphabetShiftState.isAutomaticTemporaryUpperCase()) {
+            } else if (mAlphabetShiftState.isAutomaticShifted()) {
                 // Shift key is pressed while automatic temporary upper case, we have to move to
                 // manual temporary upper case.
                 setShifted(MANUAL_SHIFT);
@@ -400,7 +400,7 @@
                     && mShiftKeyState.isPressingOnShifted() && !withSliding) {
                 // Shift has been pressed without chording while shifted state.
                 setShifted(UNSHIFT);
-            } else if (mAlphabetShiftState.isManualTemporaryUpperCaseFromAuto()
+            } else if (mAlphabetShiftState.isManualShiftedFromAutomaticShifted()
                     && mShiftKeyState.isPressing() && !withSliding) {
                 // Shift has been pressed without chording while manual temporary upper case
                 // transited from automatic temporary upper case.
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 2e7e826..0d6395d 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1470,13 +1470,12 @@
         if (ic == null)
             return;
 
-        // True if keyboard is in either chording shift or manual temporary upper case mode.
-        final boolean isManualTemporaryUpperCase = mKeyboardSwitcher.isManualTemporaryUpperCase();
-        if (EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions)
-                && !isManualTemporaryUpperCase) {
+        final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
+        // True if keyboard is in either shift chording or manual shifted state.
+        final boolean isManualShifted = (keyboard != null  && keyboard.isManualShifted());
+        if (EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) && !isManualShifted) {
             EditorInfoCompatUtils.performEditorActionNext(ic);
-        } else if (EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions)
-                && isManualTemporaryUpperCase) {
+        } else if (EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions) && isManualShifted) {
             EditorInfoCompatUtils.performEditorActionPrevious(ic);
         }
     }
@@ -1518,27 +1517,6 @@
                 mComposingStateManager.onFinishComposingText();
             }
         }
-        final KeyboardSwitcher switcher = mKeyboardSwitcher;
-        if (switcher.isShiftedOrShiftLocked()) {
-            if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT
-                    || keyCodes[0] > Character.MAX_CODE_POINT) {
-                return;
-            }
-            code = keyCodes[0];
-            if (switcher.isAlphabetMode() && Character.isLowerCase(code)) {
-                // In some locales, such as Turkish, Character.toUpperCase() may return a wrong
-                // character because it doesn't take care of locale.
-                final String upperCaseString = new String(new int[] {code}, 0, 1)
-                        .toUpperCase(mSubtypeSwitcher.getInputLocale());
-                if (upperCaseString.codePointCount(0, upperCaseString.length()) == 1) {
-                    code = upperCaseString.codePointAt(0);
-                } else {
-                    // Some keys, such as [eszett], have upper case as multi-characters.
-                    onTextInput(upperCaseString);
-                    return;
-                }
-            }
-        }
         if (isComposingWord) {
             mWordComposer.add(code, keyCodes, x, y);
             if (ic != null) {
diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
index 600f14e..cd83c3e 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
@@ -141,11 +141,6 @@
     }
 
     @Override
-    public void setShifted(boolean shifted) {
-        // Nothing to do with.
-    }
-
-    @Override
     public void showMoreKeysPanel(View parentView, Controller controller, int pointX, int pointY,
             PopupWindow window, KeyboardActionListener listener) {
         mController = controller;