diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 7de41f0a026cdbdd5f5d12229cf3f1bec092ee42..3f99cdae64eaf8ec9a0821d4463d28bb6741f908 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -123,6 +123,8 @@
         <!-- The hint icon to display on the key when keyboard is in manual temporary upper case
              mode. -->
         <attr name="manualTemporaryUpperCaseHintIcon" format="reference" />
+        <!-- The key style to specify a set of key attributes defined by <key_style/> -->
+        <attr name="keyStyle" format="string" />
     </declare-styleable>
 
     <declare-styleable name="BaseKeyboard_Row">
@@ -153,4 +155,9 @@
         <attr name="voiceKeyEnabled" format="string" />
         <attr name="hasVoiceKey" format="string" />
     </declare-styleable>
+
+    <declare-styleable name="BaseKeyboard_KeyStyle">
+        <attr name="styleName" format="string" />
+        <attr name="parentStyle" format="string" />
+    </declare-styleable>
 </resources>
diff --git a/java/res/values/keycodes.xml b/java/res/values/keycodes.xml
index cbfe89690c2e22eec911fac7d470d285eb0cbea6..54fa61026d69e05eaf34c0e1b4e6cc05f8f1e027 100644
--- a/java/res/values/keycodes.xml
+++ b/java/res/values/keycodes.xml
@@ -23,7 +23,7 @@
     <integer name="key_return">10</integer>
     <integer name="key_space">32</integer>
     <integer name="key_shift">-1</integer>
-    <integer name="key_symbol">-2</integer>
+    <integer name="key_switch_alpha_symbol">-2</integer>
     <integer name="key_delete">-5</integer>
     <!-- Keycode for F1 (function) key. This one switches between language switch & comma/.com -->
     <integer name="key_settings">-100</integer>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 018a1f98381455ec3e5925e6b3aed2bc89a58ec2..09449dc0d7d1db869a510224ed4ea087accaac12 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -219,11 +219,11 @@
     <!-- Label for soft enter key when it performs SEND action.  Must be short to fit on key! -->
     <string name="label_send_key">Send</string>
     <!-- Label for "switch to symbols" key.  Must be short to fit on key! -->
-    <string name="label_symbol_key">\?123</string>
+    <string name="label_to_symbol_key">\?123</string>
     <!-- Label for "switch to numeric" key.  Must be short to fit on key! -->
     <string name="label_phone_key">123</string>
     <!-- Label for "switch to alphabetic" key.  Must be short to fit on key! -->
-    <string name="label_alpha_key">ABC</string>
+    <string name="label_to_alpha_key">ABC</string>
     <!-- Label for ALT modifier key.  Must be short to fit on key! -->
     <string name="label_alt_key">ALT</string>
     <!-- Label for Backspace modifier key.  Must be short to fit on key! -->
diff --git a/java/res/xml-xlarge/kbd_phone.xml b/java/res/xml-xlarge/kbd_phone.xml
index f30499622ae2331766a7fae79c0ac9911583431e..4bbd69d467b6d185fdbb8d0f8f10e19246774283 100644
--- a/java/res/xml-xlarge/kbd_phone.xml
+++ b/java/res/xml-xlarge/kbd_phone.xml
@@ -69,7 +69,7 @@
     </Row>
     <Row>
         <Key
-            latin:codes="@integer/key_symbol"
+            latin:codes="@integer/key_switch_alpha_symbol"
             latin:keyLabel="@string/label_more_key"
             latin:keyLabelOption="fontItalic|alignLeft|alignBottom"
             latin:isModifier="true"
diff --git a/java/res/xml-xlarge/kbd_phone_symbols.xml b/java/res/xml-xlarge/kbd_phone_symbols.xml
index 42a6c6115fb5e36720f13a95a894068fed02f8dd..8f496c0cb3153a3567bcb035371f6e0b1dd19213 100644
--- a/java/res/xml-xlarge/kbd_phone_symbols.xml
+++ b/java/res/xml-xlarge/kbd_phone_symbols.xml
@@ -73,7 +73,7 @@
     </Row>
     <Row>
         <Key
-            latin:codes="@integer/key_symbol"
+            latin:codes="@integer/key_switch_alpha_symbol"
             latin:keyLabel="@string/label_more_key"
             latin:keyLabelOption="fontItalic|alignLeft|alignBottom"
             latin:isModifier="true"
diff --git a/java/res/xml-xlarge/kbd_qwerty_row2.xml b/java/res/xml-xlarge/kbd_qwerty_row2.xml
index 234aa0c1c94c477474584945edc3be312507e708..f1df3f2d2979dcc10cd69e810aa57800ad8cb125 100644
--- a/java/res/xml-xlarge/kbd_qwerty_row2.xml
+++ b/java/res/xml-xlarge/kbd_qwerty_row2.xml
@@ -25,8 +25,8 @@
         latin:keyWidth="8.157%p"
     >
         <Key
-            latin:codes="@integer/key_symbol"
-            latin:keyLabel="@string/label_symbol_key"
+            latin:codes="@integer/key_switch_alpha_symbol"
+            latin:keyLabel="@string/label_to_symbol_key"
             latin:keyLabelOption="fontItalic|alignLeft|alignBottom"
             latin:keyWidth="11.167%p"
             latin:isModifier="true"
diff --git a/java/res/xml-xlarge/kbd_symbols.xml b/java/res/xml-xlarge/kbd_symbols.xml
index 6ce8aad0b7dd3e68663a82d324fe01708faf0e04..99f4d81005dcb0ae63f19fd1918f40d7490d4831 100644
--- a/java/res/xml-xlarge/kbd_symbols.xml
+++ b/java/res/xml-xlarge/kbd_symbols.xml
@@ -82,8 +82,8 @@
         latin:keyWidth="8.157%p"
     >
         <Key
-            latin:codes="@integer/key_symbol"
-            latin:keyLabel="@string/label_alpha_key"
+            latin:codes="@integer/key_switch_alpha_symbol"
+            latin:keyLabel="@string/label_to_alpha_key"
             latin:keyLabelOption="fontItalic|alignLeft|alignBottom"
             latin:keyWidth="11.167%p"
             latin:isModifier="true"
diff --git a/java/res/xml-xlarge/kbd_symbols_shift.xml b/java/res/xml-xlarge/kbd_symbols_shift.xml
index 3f4cc2626b4f902d0ef310abbb5c0aaed54fa127..016b0016eb617f6dc055066790c1bd05e2f2a72c 100644
--- a/java/res/xml-xlarge/kbd_symbols_shift.xml
+++ b/java/res/xml-xlarge/kbd_symbols_shift.xml
@@ -72,8 +72,8 @@
         latin:keyWidth="8.157%p"
     >
         <Key
-            latin:codes="@integer/key_symbol"
-            latin:keyLabel="@string/label_alpha_key"
+            latin:codes="@integer/key_switch_alpha_symbol"
+            latin:keyLabel="@string/label_to_alpha_key"
             latin:keyLabelOption="fontItalic|alignLeft|alignBottom"
             latin:keyWidth="11.167%p"
             latin:isModifier="true"
diff --git a/java/res/xml/kbd_functional_key_style.xml b/java/res/xml/kbd_functional_key_style.xml
new file mode 100644
index 0000000000000000000000000000000000000000..eabaa4a7e5819665a1723428c91cccd3f399a3f0
--- /dev/null
+++ b/java/res/xml/kbd_functional_key_style.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <key-style
+        latin:styleName="functionalKeyStyle"
+        latin:isModifier="true" />
+    <key-style
+        latin:styleName="shiftKeyStyle"
+        latin:codes="@integer/key_shift"
+        latin:keyIcon="@drawable/sym_keyboard_shift"
+        latin:iconPreview="@drawable/sym_keyboard_feedback_shift"
+        latin:parentStyle="functionalKeyStyle"
+        latin:isSticky="true" />
+    <key-style
+        latin:styleName="deleteKeyStyle"
+        latin:codes="@integer/key_delete"
+        latin:keyIcon="@drawable/sym_keyboard_delete"
+        latin:iconPreview="@drawable/sym_keyboard_feedback_delete"
+        latin:parentStyle="functionalKeyStyle"
+        latin:isRepeatable="true" />
+    <switch>
+        <!-- When this qwerty keyboard has no voice key but voice key is enabled, then symbol
+             keyboard will have mic key. That means we should use "?123mic" key here. -->
+        <case
+            latin:voiceKeyEnabled="true"
+            latin:hasVoiceKey="false"
+        >
+            <key-style
+                latin:styleName="toSymbolKeyStyle"
+                latin:codes="@integer/key_switch_alpha_symbol"
+                latin:keyIcon="@drawable/sym_keyboard_123_mic"
+                latin:iconPreview="@drawable/sym_keyboard_feedback_123_mic"
+                latin:parentStyle="functionalKeyStyle" />
+        </case>
+        <default>
+            <key-style
+                latin:styleName="toSymbolKeyStyle"
+                latin:codes="@integer/key_switch_alpha_symbol"
+                latin:keyLabel="@string/label_to_symbol_key"
+                latin:parentStyle="functionalKeyStyle" />
+        </default>
+    </switch>
+    <key-style
+        latin:styleName="toAlphaKeyStyle"
+        latin:codes="@integer/key_switch_alpha_symbol"
+        latin:keyLabel="@string/label_to_alpha_key"
+        latin:parentStyle="functionalKeyStyle" />
+    <key-style
+        latin:styleName="settingsKeyStyle"
+        latin:codes="@integer/key_settings"
+        latin:keyIcon="@drawable/sym_keyboard_settings"
+        latin:iconPreview="@drawable/sym_keyboard_feedback_settings"
+        latin:parentStyle="functionalKeyStyle" />
+    <key-style
+        latin:styleName="spaceKeyStyle"
+        latin:codes="@integer/key_space"
+        latin:keyIcon="@drawable/sym_keyboard_space"
+        latin:iconPreview="@drawable/sym_keyboard_feedback_space"
+        latin:parentStyle="functionalKeyStyle" />
+    <key-style
+        latin:styleName="tabKeyStyle"
+        latin:codes="@integer/key_tab"
+        latin:keyIcon="@drawable/sym_keyboard_tab"
+        latin:iconPreview="@drawable/sym_keyboard_feedback_tab"
+        latin:parentStyle="functionalKeyStyle" />
+    <key-style
+        latin:styleName="returnKeyStyle"
+        latin:codes="@integer/key_return"
+        latin:keyIcon="@drawable/sym_keyboard_return"
+        latin:iconPreview="@drawable/sym_keyboard_feedback_return"
+        latin:parentStyle="functionalKeyStyle" />
+    <key-style
+        latin:styleName="altKeyStyle"
+        latin:codes="@integer/key_shift"
+        latin:keyLabel="@string/label_alt_key"
+        latin:parentStyle="functionalKeyStyle"
+        latin:isSticky="true" />
+    <key-style
+        latin:styleName="smileyKeyStyle"
+        latin:keyLabel=":-)"
+        latin:keyOutputText=":-) "
+        latin:keyHintIcon="@drawable/hint_popup"
+        latin:popupKeyboard="@xml/popup_smileys"
+        latin:parentStyle="functionalKeyStyle" />
+    <key-style
+        latin:styleName="micKeyStyle"
+        latin:codes="@integer/key_voice"
+        latin:popupKeyboard="@xml/popup_mic"
+        latin:keyIcon="@drawable/sym_keyboard_mic"
+        latin:iconPreview="@drawable/sym_keyboard_feedback_mic"
+        latin:keyHintIcon="@drawable/hint_popup"
+        latin:parentStyle="functionalKeyStyle" />
+</merge>
diff --git a/java/res/xml/kbd_phone.xml b/java/res/xml/kbd_phone.xml
index e6f6a09f5f001d5771674128a695b81acc5e5a4d..a01d697a7250c10887115faf75760fb518380d65 100644
--- a/java/res/xml/kbd_phone.xml
+++ b/java/res/xml/kbd_phone.xml
@@ -25,6 +25,8 @@
     latin:verticalGap="@dimen/key_bottom_gap"
     latin:keyHeight="@dimen/key_height"
 >
+    <include
+        latin:keyboardLayout="@xml/kbd_functional_key_style" />
     <Row
         latin:rowEdgeFlags="top"
     >
@@ -40,8 +42,8 @@
             latin:keyIcon="@drawable/sym_keyboard_num3" />
         <Key
             latin:keyLabel="-"
+            latin:keyStyle="functionalKeyStyle"
             latin:keyWidth="20%p"
-            latin:isModifier="true"
             latin:keyEdgeFlags="right" />
     </Row>
     <Row>
@@ -57,8 +59,8 @@
             latin:keyIcon="@drawable/sym_keyboard_num6" />
         <Key
             latin:keyLabel="."
+            latin:keyStyle="functionalKeyStyle"
             latin:keyWidth="20%p"
-            latin:isModifier="true"
             latin:keyEdgeFlags="right" />
     </Row>
     <Row>
@@ -73,19 +75,15 @@
             latin:codes="57"
             latin:keyIcon="@drawable/sym_keyboard_num9" />
         <Key
-            latin:codes="@integer/key_delete"
-            latin:keyIcon="@drawable/sym_keyboard_delete"
-            latin:iconPreview="@drawable/sym_keyboard_feedback_delete"
+            latin:keyStyle="deleteKeyStyle"
             latin:keyWidth="20%p"
-            latin:isModifier="true"
-            latin:isRepeatable="true"
             latin:keyEdgeFlags="right" />
     </Row>
     <Row
         latin:rowEdgeFlags="bottom"
     >
         <Key
-            latin:codes="@integer/key_symbol"
+            latin:codes="@integer/key_switch_alpha_symbol"
             latin:keyIcon="@drawable/sym_keyboard_numalt"
             latin:iconPreview="@drawable/sym_keyboard_feedback_numalt"
             latin:keyEdgeFlags="left" />
@@ -97,10 +95,8 @@
             latin:keyIcon="@drawable/sym_keyboard_space"
             latin:iconPreview="@drawable/sym_keyboard_feedback_space" />
         <Key
-            latin:codes="@integer/key_return"
-            latin:keyIcon="@drawable/sym_keyboard_return"
+            latin:keyStyle="returnKeyStyle"
             latin:keyWidth="20%p"
-            latin:isModifier="true"
             latin:keyEdgeFlags="right" />
     </Row>
 </Keyboard>
diff --git a/java/res/xml/kbd_phone_black.xml b/java/res/xml/kbd_phone_black.xml
index 86759d676a05ed617eef8bfd050530b2ca85f498..75ce34a74811cedda0967f5a865c31c9e789cca0 100644
--- a/java/res/xml/kbd_phone_black.xml
+++ b/java/res/xml/kbd_phone_black.xml
@@ -82,7 +82,7 @@
         latin:rowEdgeFlags="bottom"
     >
         <Key
-            latin:codes="@integer/key_symbol"
+            latin:codes="@integer/key_switch_alpha_symbol"
             latin:keyIcon="@drawable/sym_bkeyboard_numalt"
             latin:iconPreview="@drawable/sym_keyboard_feedback_numalt" />
         <Key
diff --git a/java/res/xml/kbd_phone_symbols.xml b/java/res/xml/kbd_phone_symbols.xml
index 1c691d2a54d19bb53870c82770460a5f0b9a398c..d53107ad51bcb225952a30fd9c3acf5b0901c416 100644
--- a/java/res/xml/kbd_phone_symbols.xml
+++ b/java/res/xml/kbd_phone_symbols.xml
@@ -25,6 +25,7 @@
     latin:verticalGap="@dimen/key_bottom_gap"
     latin:keyHeight="@dimen/key_height"
 >
+    <include latin:keyboardLayout="@xml/kbd_functional_key_style" />
     <Row
         latin:rowEdgeFlags="top"
     >
@@ -37,8 +38,8 @@
             latin:keyLabel=")" />
         <Key
             latin:keyLabel="-"
+            latin:keyStyle="functionalKeyStyle"
             latin:keyWidth="20%p"
-            latin:isModifier="true"
             latin:keyEdgeFlags="right" />
     </Row>
     <Row>
@@ -54,8 +55,8 @@
             latin:keyLabel="," />
         <Key
             latin:keyLabel="."
+            latin:keyStyle="functionalKeyStyle"
             latin:keyWidth="20%p"
-            latin:isModifier="true"
             latin:keyEdgeFlags="right" />
     </Row>
     <Row>
@@ -71,19 +72,15 @@
             latin:codes="35"
             latin:keyIcon="@drawable/sym_keyboard_numpound" />
         <Key
-            latin:codes="@integer/key_delete"
-            latin:keyIcon="@drawable/sym_keyboard_delete"
-            latin:iconPreview="@drawable/sym_keyboard_feedback_delete"
+            latin:keyStyle="deleteKeyStyle"
             latin:keyWidth="20%p"
-            latin:isModifier="true"
-            latin:isRepeatable="true"
             latin:keyEdgeFlags="right" />
     </Row>
     <Row
         latin:rowEdgeFlags="bottom"
     >
         <Key
-            latin:codes="@integer/key_symbol"
+            latin:codes="@integer/key_switch_alpha_symbol"
             latin:keyLabel="@string/label_phone_key"
             latin:keyEdgeFlags="left" />
         <Key
@@ -93,10 +90,8 @@
             latin:keyIcon="@drawable/sym_keyboard_space"
             latin:iconPreview="@drawable/sym_keyboard_feedback_space" />
         <Key
-            latin:codes="@integer/key_return"
-            latin:keyIcon="@drawable/sym_keyboard_return"
+            latin:keyStyle="returnKeyStyle"
             latin:keyWidth="20%p"
-            latin:isModifier="true"
             latin:keyEdgeFlags="right" />
     </Row>
 </Keyboard>
diff --git a/java/res/xml/kbd_phone_symbols_black.xml b/java/res/xml/kbd_phone_symbols_black.xml
index 3e46c5307718f83ffe1c6af9229c05bace4cda6e..06db969edd3b687df21fe8cd74f16e70ef317ea2 100644
--- a/java/res/xml/kbd_phone_symbols_black.xml
+++ b/java/res/xml/kbd_phone_symbols_black.xml
@@ -80,7 +80,7 @@
         latin:rowEdgeFlags="bottom"
     >
         <Key
-            latin:codes="@integer/key_symbol"
+            latin:codes="@integer/key_switch_alpha_symbol"
             latin:keyLabel="@string/label_phone_key"
             latin:keyEdgeFlags="left" />
         <Key
diff --git a/java/res/xml/kbd_qwerty.xml b/java/res/xml/kbd_qwerty.xml
index 517b4fe5c68e53824d23dc2dd1ada0ee224aa8c8..aac4dfaab24d811b909743cf7b5f597cb81c1984 100644
--- a/java/res/xml/kbd_qwerty.xml
+++ b/java/res/xml/kbd_qwerty.xml
@@ -25,6 +25,8 @@
     latin:verticalGap="@dimen/key_bottom_gap"
     latin:keyHeight="@dimen/key_height"
 >
+    <include
+        latin:keyboardLayout="@xml/kbd_functional_key_style" />
     <Row
         latin:rowEdgeFlags="top"
     >
@@ -117,12 +119,8 @@
     </Row>
     <Row>
         <Key
-            latin:codes="@integer/key_shift"
-            latin:keyIcon="@drawable/sym_keyboard_shift"
-            latin:iconPreview="@drawable/sym_keyboard_feedback_shift"
+            latin:keyStyle="shiftKeyStyle"
             latin:keyWidth="15%p"
-            latin:isModifier="true"
-            latin:isSticky="true"
             latin:keyEdgeFlags="left" />
         <Key
             latin:keyLabel="z"
@@ -147,13 +145,10 @@
         <Key
             latin:keyLabel="m" />
         <Key
-            latin:codes="@integer/key_delete"
-            latin:keyIcon="@drawable/sym_keyboard_delete"
-            latin:iconPreview="@drawable/sym_keyboard_feedback_delete"
+            latin:keyStyle="deleteKeyStyle"
             latin:keyWidth="15%p"
-            latin:isModifier="true"
-            latin:isRepeatable="true"
             latin:keyEdgeFlags="right" />
     </Row>
-    <include latin:keyboardLayout="@xml/kbd_qwerty_row4" />
+    <include
+        latin:keyboardLayout="@xml/kbd_qwerty_row4" />
 </Keyboard>
diff --git a/java/res/xml/kbd_qwerty_black_symbol.xml b/java/res/xml/kbd_qwerty_black_symbol.xml
index c1ef170f9bb18354360406ac50d9d5d0cb9b8a40..840db9c5a5a90d0d73cdb7388b1cdf7bc43f5b4e 100644
--- a/java/res/xml/kbd_qwerty_black_symbol.xml
+++ b/java/res/xml/kbd_qwerty_black_symbol.xml
@@ -34,7 +34,7 @@
                     latin:hasVoiceKey="false"
                 >
                     <Key
-                        latin:codes="@integer/key_symbol"
+                        latin:codes="@integer/key_switch_alpha_symbol"
                         latin:keyIcon="@drawable/sym_bkeyboard_123_mic"
                         latin:iconPreview="@drawable/sym_keyboard_feedback_123_mic"
                         latin:keyWidth="20%p"
@@ -43,7 +43,7 @@
                 </case>
                 <default>
                     <Key
-                        latin:codes="@integer/key_symbol"
+                        latin:codes="@integer/key_switch_alpha_symbol"
                         latin:keyLabel="@string/label_symbol_key"
                         latin:keyWidth="20%p"
                         latin:isModifier="true"
@@ -63,7 +63,7 @@
                     latin:hasVoiceKey="false"
                 >
                     <Key
-                        latin:codes="@integer/key_symbol"
+                        latin:codes="@integer/key_switch_alpha_symbol"
                         latin:keyIcon="@drawable/sym_bkeyboard_123_mic"
                         latin:iconPreview="@drawable/sym_keyboard_feedback_123_mic"
                         latin:keyWidth="15%p"
@@ -72,7 +72,7 @@
                 </case>
                 <default>
                     <Key
-                        latin:codes="@integer/key_symbol"
+                        latin:codes="@integer/key_switch_alpha_symbol"
                         latin:keyLabel="@string/label_symbol_key"
                         latin:keyWidth="15%p"
                         latin:isModifier="true"
diff --git a/java/res/xml/kbd_qwerty_f1.xml b/java/res/xml/kbd_qwerty_f1.xml
index 23e494cc5520368dcf85e28783f4923c7d810df3..1f0ccfb98de4d430ea03482e1f78a911a0a3396a 100644
--- a/java/res/xml/kbd_qwerty_f1.xml
+++ b/java/res/xml/kbd_qwerty_f1.xml
@@ -40,23 +40,24 @@
                 latin:keyHintIcon="@drawable/hint_popup"
                 latin:isModifier="true" />
         </case>
-        <case
-            latin:hasVoiceKey="true"
-        >
-            <Key
-                latin:codes="@integer/key_voice"
-                latin:popupKeyboard="@xml/popup_mic"
-                latin:keyIcon="@drawable/sym_keyboard_mic"
-                latin:iconPreview="@drawable/sym_keyboard_feedback_mic"
-                latin:keyHintIcon="@drawable/hint_popup"
-                latin:isModifier="true" />
-        </case>
         <default>
-            <Key
-                latin:keyLabel=","
-                latin:popupKeyboard="@xml/popup_comma"
-                latin:keyHintIcon="@drawable/hint_popup"
-                latin:isModifier="true" />
+            <switch>
+                <case
+                    latin:hasVoiceKey="true"
+                >
+                    <Key
+                        latin:keyStyle="micKeyStyle" />
+                </case>
+                <case
+                    latin:hasVoiceKey="false"
+                >
+                    <Key
+                        latin:keyLabel=","
+                        latin:popupKeyboard="@xml/popup_comma"
+                        latin:keyHintIcon="@drawable/hint_popup"
+                        latin:isModifier="true" />
+                </case>
+            </switch>
         </default>
     </switch>
 </merge>
diff --git a/java/res/xml/kbd_qwerty_row4.xml b/java/res/xml/kbd_qwerty_row4.xml
index a5113ea76155571e70a0027d452a541a28e75cb0..cd03c51fc97a257fe2249009c9e4c9dde3a5c715 100644
--- a/java/res/xml/kbd_qwerty_row4.xml
+++ b/java/res/xml/kbd_qwerty_row4.xml
@@ -29,8 +29,10 @@
             <case
                 latin:hasSettingsKey="false"
             >
-                <include
-                    latin:keyboardLayout="@xml/kbd_qwerty_symbol" />
+                <Key
+                    latin:keyStyle="toSymbolKeyStyle"
+                    latin:keyWidth="20%p"
+                    latin:keyEdgeFlags="left" />
                 <include
                     latin:keyboardLayout="@xml/kbd_qwerty_f1" />
                 <switch>
@@ -38,52 +40,36 @@
                         latin:mode="web"
                     >
                         <Key
-                            latin:codes="@integer/key_space"
-                            latin:keyIcon="@drawable/sym_keyboard_space"
-                            latin:iconPreview="@drawable/sym_keyboard_feedback_space"
-                            latin:keyWidth="20%p"
-                            latin:isModifier="true" />
+                            latin:keyStyle="spaceKeyStyle"
+                            latin:keyWidth="20%p" />
                         <Key
-                            latin:codes="@integer/key_tab"
-                            latin:keyIcon="@drawable/sym_keyboard_tab"
-                            latin:iconPreview="@drawable/sym_keyboard_feedback_tab"
-                            latin:keyWidth="20%p"
-                            latin:isModifier="true" />
+                            latin:keyStyle="tabKeyStyle"
+                            latin:keyWidth="20%p" />
                     </case>
                     <default>
                         <Key
-                            latin:codes="@integer/key_space"
-                            latin:keyIcon="@drawable/sym_keyboard_space"
-                            latin:iconPreview="@drawable/sym_keyboard_feedback_space"
-                            latin:keyWidth="40%p"
-                            latin:isModifier="true" />
+                            latin:keyStyle="spaceKeyStyle"
+                            latin:keyWidth="40%p" />
                     </default>
                 </switch>
                 <Key
                     latin:keyLabel="."
                     latin:keyHintIcon="@drawable/hint_popup"
                     latin:popupKeyboard="@xml/popup_punctuation"
-                    latin:isModifier="true" />
+                    latin:keyStyle="functionalKeyStyle" />
                 <switch>
                     <case
                         latin:mode="im"
                     >
                         <Key
-                            latin:keyLabel=":-)"
-                            latin:keyOutputText=":-) "
-                            latin:keyHintIcon="@drawable/hint_popup"
-                            latin:popupKeyboard="@xml/popup_smileys"
+                            latin:keyStyle="smileyKeyStyle"
                             latin:keyWidth="20%p"
-                            latin:isModifier="true"
                             latin:keyEdgeFlags="right" />
                     </case>
                     <default>
                         <Key
-                            latin:codes="@integer/key_return"
-                            latin:keyIcon="@drawable/sym_keyboard_return"
-                            latin:iconPreview="@drawable/sym_keyboard_feedback_return"
+                            latin:keyStyle="returnKeyStyle"
                             latin:keyWidth="20%p"
-                            latin:isModifier="true"
                             latin:keyEdgeFlags="right" />
                     </default>
                 </switch>
@@ -91,13 +77,12 @@
             <case
                 latin:hasSettingsKey="true"
             >
-                <include
-                    latin:keyboardLayout="@xml/kbd_qwerty_symbol" />
                 <Key
-                    latin:codes="@integer/key_settings"
-                    latin:keyIcon="@drawable/sym_keyboard_settings"
-                    latin:iconPreview="@drawable/sym_keyboard_feedback_settings"
-                    latin:isModifier="true" />
+                    latin:keyStyle="toSymbolKeyStyle"
+                    latin:keyWidth="15%p"
+                    latin:keyEdgeFlags="left" />
+                <Key
+                    latin:keyStyle="settingsKeyStyle" />
                 <include
                     latin:keyboardLayout="@xml/kbd_qwerty_f1" />
                 <switch>
@@ -105,62 +90,43 @@
                         latin:mode="web"
                     >
                         <Key
-                            latin:codes="@integer/key_space"
-                            latin:keyIcon="@drawable/sym_keyboard_space"
-                            latin:iconPreview="@drawable/sym_keyboard_feedback_space"
-                            latin:keyWidth="30%p"
-                            latin:isModifier="true" />
+                            latin:keyStyle="spaceKeyStyle"
+                            latin:keyWidth="30%p" />
                         <Key
-                            latin:codes="@integer/key_tab"
-                            latin:keyIcon="@drawable/sym_keyboard_tab"
-                            latin:iconPreview="@drawable/sym_keyboard_feedback_tab"
-                            latin:isModifier="true" />
+                            latin:keyStyle="tabKeyStyle" />
                     </case>
                     <default>
                         <Key
-                            latin:codes="@integer/key_space"
-                            latin:keyIcon="@drawable/sym_keyboard_space"
-                            latin:iconPreview="@drawable/sym_keyboard_feedback_space"
-                            latin:keyWidth="30%p"
-                            latin:isModifier="true" />
+                            latin:keyStyle="spaceKeyStyle"
+                            latin:keyWidth="30%p" />
                     </default>
                 </switch>
                 <Key
                     latin:keyLabel="."
                     latin:keyHintIcon="@drawable/hint_popup"
                     latin:popupKeyboard="@xml/popup_punctuation"
-                    latin:isModifier="true" />
+                    latin:keyStyle="functionalKeyStyle" />
                 <switch>
                     <case
                         latin:mode="im"
                     >
                         <Key
-                            latin:keyLabel=":-)"
-                            latin:keyOutputText=":-) "
-                            latin:keyHintIcon="@drawable/hint_popup"
-                            latin:popupKeyboard="@xml/popup_smileys"
+                            latin:keyStyle="smileyKeyStyle"
                             latin:keyWidth="25%p"
-                            latin:isModifier="true"
                             latin:keyEdgeFlags="right" />
                     </case>
                     <case
                         latin:mode="web"
                     >
                         <Key
-                            latin:codes="@integer/key_return"
-                            latin:keyIcon="@drawable/sym_keyboard_return"
-                            latin:iconPreview="@drawable/sym_keyboard_feedback_return"
+                            latin:keyStyle="returnKeyStyle"
                             latin:keyWidth="15%p"
-                            latin:isModifier="true"
                             latin:keyEdgeFlags="right" />
                     </case>
                     <default>
                         <Key
-                            latin:codes="@integer/key_return"
-                            latin:keyIcon="@drawable/sym_keyboard_return"
-                            latin:iconPreview="@drawable/sym_keyboard_feedback_return"
+                            latin:keyStyle="returnKeyStyle"
                             latin:keyWidth="25%p"
-                            latin:isModifier="true"
                             latin:keyEdgeFlags="right" />
                     </default>
                 </switch>
diff --git a/java/res/xml/kbd_qwerty_symbol.xml b/java/res/xml/kbd_qwerty_symbol.xml
deleted file mode 100644
index e90091c36ac20d2cd5cc52c4911d64986f66f968..0000000000000000000000000000000000000000
--- a/java/res/xml/kbd_qwerty_symbol.xml
+++ /dev/null
@@ -1,84 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
-    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
-    <switch>
-        <case
-            latin:hasSettingsKey="false"
-        >
-            <switch>
-                <!-- When this qwerty keyboard has no voice key but voice key is enabled, then
-                     symbol keyboard will have mic key. That means we should use "?123mic" key here.
-                     -->
-                <case
-                    latin:voiceKeyEnabled="true"
-                    latin:hasVoiceKey="false"
-                >
-                    <Key
-                        latin:codes="@integer/key_symbol"
-                        latin:keyIcon="@drawable/sym_keyboard_123_mic"
-                        latin:iconPreview="@drawable/sym_keyboard_feedback_123_mic"
-                        latin:keyWidth="20%p"
-                        latin:isModifier="true"
-                        latin:keyEdgeFlags="left" />
-                </case>
-                <default>
-                    <Key
-                        latin:codes="@integer/key_symbol"
-                        latin:keyLabel="@string/label_symbol_key"
-                        latin:keyWidth="20%p"
-                        latin:isModifier="true"
-                        latin:keyEdgeFlags="left" />
-                </default>
-            </switch>
-        </case>
-        <case
-            latin:hasSettingsKey="true"
-        >
-            <switch>
-                <!-- When this qwerty keyboard has no voice key but voice key is enabled, then
-                     symbol keyboard will have mic key. That means we should use "?123mic" key here.
-                     -->
-                <case
-                    latin:voiceKeyEnabled="true"
-                    latin:hasVoiceKey="false"
-                >
-                    <Key
-                        latin:codes="@integer/key_symbol"
-                        latin:keyIcon="@drawable/sym_keyboard_123_mic"
-                        latin:iconPreview="@drawable/sym_keyboard_feedback_123_mic"
-                        latin:keyWidth="15%p"
-                        latin:isModifier="true"
-                        latin:keyEdgeFlags="left" />
-                </case>
-                <default>
-                    <Key
-                        latin:codes="@integer/key_symbol"
-                        latin:keyLabel="@string/label_symbol_key"
-                        latin:keyWidth="15%p"
-                        latin:isModifier="true"
-                        latin:keyEdgeFlags="left" />
-                </default>
-            </switch>
-        </case>
-    </switch>
-</merge>
diff --git a/java/res/xml/kbd_symbols.xml b/java/res/xml/kbd_symbols.xml
index 55b7681f9c47063d04c224399a870936e8af6aa6..e9df8163a0e4aae9053d1cf70e684cd911372f6e 100644
--- a/java/res/xml/kbd_symbols.xml
+++ b/java/res/xml/kbd_symbols.xml
@@ -25,6 +25,8 @@
     latin:verticalGap="@dimen/key_bottom_gap"
     latin:keyHeight="@dimen/key_height"
 >
+    <include
+        latin:keyboardLayout="@xml/kbd_functional_key_style" />
     <Row
         latin:rowEdgeFlags="top"
     >
@@ -105,11 +107,8 @@
     </Row>
     <Row>
         <Key
-            latin:codes="@integer/key_shift"
-            latin:keyLabel="@string/label_alt_key"
+            latin:keyStyle="altKeyStyle"
             latin:keyWidth="15%p"
-            latin:isModifier="true"
-            latin:isSticky="true"
             latin:keyEdgeFlags="left" />
         <Key
             latin:keyLabel="!"
@@ -134,12 +133,8 @@
             latin:popupKeyboard="@xml/kbd_popup_template"
             latin:popupCharacters="¿" />
         <Key
-            latin:codes="@integer/key_delete"
-            latin:keyIcon="@drawable/sym_keyboard_delete"
-            latin:iconPreview="@drawable/sym_keyboard_feedback_delete"
+            latin:keyStyle="deleteKeyStyle"
             latin:keyWidth="15%p"
-            latin:isModifier="true"
-            latin:isRepeatable="true"
             latin:keyEdgeFlags="right" />
     </Row>
     <include latin:keyboardLayout="@xml/kbd_symbols_row4" />
diff --git a/java/res/xml/kbd_symbols_black_row4.xml b/java/res/xml/kbd_symbols_black_row4.xml
index a50f8c05dc2dc6aaeac51c07a447e2adc6d03997..57f491b97fe34ca4495125b2c3c30f14828e6cf7 100644
--- a/java/res/xml/kbd_symbols_black_row4.xml
+++ b/java/res/xml/kbd_symbols_black_row4.xml
@@ -29,8 +29,8 @@
                 latin:hasSettingsKey="false"
             >
                 <Key
-                    latin:codes="@integer/key_symbol"
-                    latin:keyLabel="@string/label_alpha_key"
+                    latin:codes="@integer/key_switch_alpha_symbol"
+                    latin:keyLabel="@string/label_to_alpha_key"
                     latin:keyWidth="20%p"
                     latin:keyEdgeFlags="left" />
                 <include
@@ -70,8 +70,8 @@
                 latin:hasSettingsKey="true"
             >
                 <Key
-                    latin:codes="@integer/key_symbol"
-                    latin:keyLabel="@string/label_alpha_key"
+                    latin:codes="@integer/key_switch_alpha_symbol"
+                    latin:keyLabel="@string/label_to_alpha_key"
                     latin:keyWidth="15%p"
                     latin:keyEdgeFlags="left" />
                 <Key
diff --git a/java/res/xml/kbd_symbols_f1.xml b/java/res/xml/kbd_symbols_f1.xml
index 39c411a9cd57461d562d91813acc3afaea15d662..07ee4edd3b6e4501dc2d8b965578af8e974b7967 100644
--- a/java/res/xml/kbd_symbols_f1.xml
+++ b/java/res/xml/kbd_symbols_f1.xml
@@ -26,12 +26,7 @@
             latin:hasVoiceKey="true"
         >
             <Key
-                latin:codes="@integer/key_voice"
-                latin:popupKeyboard="@xml/popup_mic"
-                latin:keyIcon="@drawable/sym_keyboard_mic"
-                latin:iconPreview="@drawable/sym_keyboard_feedback_mic"
-                latin:keyHintIcon="@drawable/hint_popup"
-                latin:isModifier="true" />
+                latin:keyStyle="micKeyStyle" />
         </case>
         <case
             latin:hasVoiceKey="false"
@@ -40,7 +35,7 @@
                 latin:keyLabel=","
                 latin:popupKeyboard="@xml/popup_comma"
                 latin:keyHintIcon="@drawable/hint_popup"
-                latin:isModifier="true" />
+                latin:keyStyle="functionalKeyStyle" />
         </case>
     </switch>
 </merge>
diff --git a/java/res/xml/kbd_symbols_row4.xml b/java/res/xml/kbd_symbols_row4.xml
index f012a4d25bc4d2d25d87dfac3bf15b531ba4bdb6..1a5417d08fb2c70f13eaae9a7ceba8d1e36bab0d 100644
--- a/java/res/xml/kbd_symbols_row4.xml
+++ b/java/res/xml/kbd_symbols_row4.xml
@@ -29,44 +29,32 @@
                 latin:hasSettingsKey="false"
             >
                 <Key
-                    latin:codes="@integer/key_symbol"
-                    latin:keyLabel="@string/label_alpha_key"
+                    latin:keyStyle="toAlphaKeyStyle"
                     latin:keyWidth="20%p"
-                    latin:isModifier="true"
                     latin:keyEdgeFlags="left" />
                 <include
                     latin:keyboardLayout="@xml/kbd_symbols_f1" />
                 <Key
-                    latin:codes="@integer/key_space"
-                    latin:keyIcon="@drawable/sym_keyboard_space"
-                    latin:iconPreview="@drawable/sym_keyboard_feedback_space"
-                    latin:keyWidth="40%p"
-                    latin:isModifier="true" />
+                    latin:keyStyle="spaceKeyStyle"
+                    latin:keyWidth="40%p" />
                 <Key
                     latin:keyLabel="."
                     latin:keyHintIcon="@drawable/hint_popup"
                     latin:popupKeyboard="@xml/popup_punctuation"
-                    latin:isModifier="true" />
+                    latin:keyStyle="functionalKeyStyle" />
                 <switch>
                     <case
                         latin:mode="im"
                     >
                         <Key
-                            latin:keyLabel=":-)"
-                            latin:keyOutputText=":-) "
-                            latin:keyHintIcon="@drawable/hint_popup"
-                            latin:popupKeyboard="@xml/popup_smileys"
+                            latin:keyStyle="smileyKeyStyle"
                             latin:keyWidth="20%p"
-                            latin:isModifier="true"
                             latin:keyEdgeFlags="right" />
                     </case>
                     <default>
                         <Key
-                            latin:codes="@integer/key_return"
-                            latin:keyIcon="@drawable/sym_keyboard_return"
-                            latin:iconPreview="@drawable/sym_keyboard_feedback_return"
+                            latin:keyStyle="returnKeyStyle"
                             latin:keyWidth="20%p"
-                            latin:isModifier="true"
                             latin:keyEdgeFlags="right" />
                     </default>
                 </switch>
@@ -75,49 +63,34 @@
                 latin:hasSettingsKey="true"
             >
                 <Key
-                    latin:codes="@integer/key_symbol"
-                    latin:keyLabel="@string/label_alpha_key"
+                    latin:keyStyle="toAlphaKeyStyle"
                     latin:keyWidth="15%p"
-                    latin:isModifier="true"
                     latin:keyEdgeFlags="left" />
                 <Key
-                    latin:codes="@integer/key_settings"
-                    latin:keyIcon="@drawable/sym_keyboard_settings"
-                    latin:iconPreview="@drawable/sym_keyboard_feedback_settings"
-                    latin:isModifier="true" />
+                    latin:keyStyle="settingsKeyStyle" />
                 <include
                     latin:keyboardLayout="@xml/kbd_symbols_f1" />
                 <Key
-                    latin:codes="@integer/key_space"
-                    latin:keyIcon="@drawable/sym_keyboard_space"
-                    latin:iconPreview="@drawable/sym_keyboard_feedback_space"
-                    latin:keyWidth="30%p"
-                    latin:isModifier="true" />
+                    latin:keyStyle="spaceKeyStyle"
+                    latin:keyWidth="30%p" />
                 <Key
                     latin:keyLabel="."
                     latin:keyHintIcon="@drawable/hint_popup"
                     latin:popupKeyboard="@xml/popup_punctuation"
-                    latin:isModifier="true" />
+                    latin:keyStyle="functionalKeyStyle" />
                 <switch>
                     <case
                         latin:mode="im"
                     >
                         <Key
-                            latin:keyLabel=":-)"
-                            latin:keyOutputText=":-) "
-                            latin:keyHintIcon="@drawable/hint_popup"
-                            latin:popupKeyboard="@xml/popup_smileys"
+                            latin:keyStyle="smileyKeyStyle"
                             latin:keyWidth="25%p"
-                            latin:isModifier="true"
                             latin:keyEdgeFlags="right" />
                     </case>
                     <default>
                         <Key
-                            latin:codes="@integer/key_return"
-                            latin:keyIcon="@drawable/sym_keyboard_return"
-                            latin:iconPreview="@drawable/sym_keyboard_feedback_return"
+                            latin:keyStyle="returnKeyStyle"
                             latin:keyWidth="25%p"
-                            latin:isModifier="true"
                             latin:keyEdgeFlags="right" />
                     </default>
                 </switch>
diff --git a/java/res/xml/kbd_symbols_shift.xml b/java/res/xml/kbd_symbols_shift.xml
index 52796561d500f997f75469a58a4ef5842002f838..f3e79f71eda27a1f9dd6b2888a5e9365ee9b7512 100644
--- a/java/res/xml/kbd_symbols_shift.xml
+++ b/java/res/xml/kbd_symbols_shift.xml
@@ -25,6 +25,8 @@
     latin:verticalGap="@dimen/key_bottom_gap"
     latin:keyHeight="@dimen/key_height"
 >
+    <include
+        latin:keyboardLayout="@xml/kbd_functional_key_style" />
     <Row
         latin:rowEdgeFlags="top"
     >
@@ -58,7 +60,8 @@
     <Row>
         <Key
             latin:codes="@integer/key_tab"
-            latin:keyLabel="\u21E5"
+            latin:keyIcon="@drawable/sym_keyboard_tab"
+            latin:iconPreview="@drawable/sym_keyboard_feedback_tab"
             latin:keyEdgeFlags="left" />
         <Key
             latin:keyLabel="£" />
@@ -86,11 +89,8 @@
     </Row>
     <Row>
         <Key
-            latin:codes="@integer/key_shift"
-            latin:keyLabel="@string/label_alt_key"
+            latin:keyStyle="shiftKeyStyle"
             latin:keyWidth="15%p"
-            latin:isModifier="true"
-            latin:isSticky="true"
             latin:keyEdgeFlags="left" />
         <Key
             latin:keyLabel="â„¢" />
@@ -113,12 +113,8 @@
             latin:popupKeyboard="@xml/kbd_popup_template"
             latin:popupCharacters="≥»›" />
         <Key
-            latin:codes="@integer/key_delete"
-            latin:keyIcon="@drawable/sym_keyboard_delete"
-            latin:iconPreview="@drawable/sym_keyboard_feedback_delete"
+            latin:keyStyle="deleteKeyStyle"
             latin:keyWidth="15%p"
-            latin:isModifier="true"
-            latin:isRepeatable="true"
             latin:keyEdgeFlags="right" />
     </Row>
     <include latin:keyboardLayout="@xml/kbd_symbols_shift_row4" />
diff --git a/java/res/xml/kbd_symbols_shift_black_row4.xml b/java/res/xml/kbd_symbols_shift_black_row4.xml
index 4e5ddcdd4b24ea6df970657b1c87f3e1ed8315ec..731cc6eb85cf54580af688c36189cf98e6a54525 100644
--- a/java/res/xml/kbd_symbols_shift_black_row4.xml
+++ b/java/res/xml/kbd_symbols_shift_black_row4.xml
@@ -29,8 +29,8 @@
                 latin:hasSettingsKey="false"
             >
                 <Key
-                    latin:codes="@integer/key_symbol"
-                    latin:keyLabel="@string/label_alpha_key"
+                    latin:codes="@integer/key_switch_alpha_symbol"
+                    latin:keyLabel="@string/label_to_alpha_key"
                     latin:keyWidth="20%p"
                     latin:keyEdgeFlags="left" />
                 <Key
@@ -68,8 +68,8 @@
                 latin:hasSettingsKey="true"
             >
                 <Key
-                    latin:codes="@integer/key_symbol"
-                    latin:keyLabel="@string/label_alpha_key"
+                    latin:codes="@integer/key_switch_alpha_symbol"
+                    latin:keyLabel="@string/label_to_alpha_key"
                     latin:keyWidth="15%p"
                     latin:keyEdgeFlags="left" />
                 <Key
diff --git a/java/res/xml/kbd_symbols_shift_row4.xml b/java/res/xml/kbd_symbols_shift_row4.xml
index 170c8b90aa5a719e35bc3d718a438e05e80c84a0..9159bab24d3686ddf279b983ea86550c80130494 100644
--- a/java/res/xml/kbd_symbols_shift_row4.xml
+++ b/java/res/xml/kbd_symbols_shift_row4.xml
@@ -29,43 +29,31 @@
                 latin:hasSettingsKey="false"
             >
                 <Key
-                    latin:codes="@integer/key_symbol"
-                    latin:keyLabel="@string/label_alpha_key"
+                    latin:keyStyle="toAlphaKeyStyle"
                     latin:keyWidth="20%p"
-                    latin:isModifier="true"
                     latin:keyEdgeFlags="left" />
                 <Key
                     latin:keyLabel="„"
-                    latin:isModifier="true" />
+                    latin:keyStyle="functionalKeyStyle" />
                 <Key
-                    latin:codes="@integer/key_space"
-                    latin:keyIcon="@drawable/sym_keyboard_space"
-                    latin:iconPreview="@drawable/sym_keyboard_feedback_space"
-                    latin:keyWidth="40%p"
-                    latin:isModifier="true" />
+                    latin:keyStyle="spaceKeyStyle"
+                    latin:keyWidth="40%p" />
                 <Key
                     latin:keyLabel="…"
-                    latin:isModifier="true" />
+                    latin:keyStyle="functionalKeyStyle" />
                 <switch>
                     <case
                         latin:mode="im"
                     >
                         <Key
-                            latin:keyLabel=":-)"
-                            latin:keyOutputText=":-) "
-                            latin:keyHintIcon="@drawable/hint_popup"
-                            latin:popupKeyboard="@xml/popup_smileys"
+                            latin:keyStyle="smileyKeyStyle"
                             latin:keyWidth="20%p"
-                            latin:isModifier="true"
                             latin:keyEdgeFlags="right" />
                     </case>
                     <default>
                         <Key
-                            latin:codes="@integer/key_return"
-                            latin:keyIcon="@drawable/sym_keyboard_return"
-                            latin:iconPreview="@drawable/sym_keyboard_feedback_return"
+                            latin:keyStyle="returnKeyStyle"
                             latin:keyWidth="20%p"
-                            latin:isModifier="true"
                             latin:keyEdgeFlags="right" />
                     </default>
                 </switch>
@@ -74,48 +62,33 @@
                 latin:hasSettingsKey="true"
             >
                 <Key
-                    latin:codes="@integer/key_symbol"
-                    latin:keyLabel="@string/label_alpha_key"
+                    latin:keyStyle="toAlphaKeyStyle"
                     latin:keyWidth="15%p"
-                    latin:isModifier="true"
                     latin:keyEdgeFlags="left" />
                 <Key
-                    latin:codes="@integer/key_settings"
-                    latin:keyIcon="@drawable/sym_keyboard_settings"
-                    latin:iconPreview="@drawable/sym_keyboard_feedback_settings"
-                    latin:isModifier="true" />
+                    latin:keyStyle="settingsKeyStyle" />
                 <Key
                     latin:keyLabel="„"
-                    latin:isModifier="true" />
+                    latin:keyStyle="functionalKeyStyle" />
                 <Key
-                    latin:codes="@integer/key_space"
-                    latin:keyIcon="@drawable/sym_keyboard_space"
-                    latin:iconPreview="@drawable/sym_keyboard_feedback_space"
-                    latin:keyWidth="30%p"
-                    latin:isModifier="true" />
+                    latin:keyStyle="spaceKeyStyle"
+                    latin:keyWidth="30%p" />
                 <Key
                     latin:keyLabel="…"
-                    latin:isModifier="true" />
+                    latin:keyStyle="functionalKeyStyle" />
                 <switch>
                     <case
                         latin:mode="im"
                     >
                         <Key
-                            latin:keyLabel=":-)"
-                            latin:keyOutputText=":-) "
-                            latin:keyHintIcon="@drawable/hint_popup"
-                            latin:popupKeyboard="@xml/popup_smileys"
+                            latin:keyStyle="smileyKeyStyle"
                             latin:keyWidth="25%p"
-                            latin:isModifier="true"
                             latin:keyEdgeFlags="right" />
                     </case>
                     <default>
                         <Key
-                            latin:codes="@integer/key_return"
-                            latin:keyIcon="@drawable/sym_keyboard_return"
-                            latin:iconPreview="@drawable/sym_keyboard_feedback_return"
+                            latin:keyStyle="returnKeyStyle"
                             latin:keyWidth="25%p"
-                            latin:isModifier="true"
                             latin:keyEdgeFlags="right" />
                     </default>
                 </switch>
diff --git a/java/src/com/android/inputmethod/latin/BaseKeyboard.java b/java/src/com/android/inputmethod/latin/BaseKeyboard.java
index cb0ac216ce69597f205d7c123202246a5aaf8f5f..485cc3153f001ae00b2e0c763b547b5fc0b6cb99 100644
--- a/java/src/com/android/inputmethod/latin/BaseKeyboard.java
+++ b/java/src/com/android/inputmethod/latin/BaseKeyboard.java
@@ -16,6 +16,8 @@
 
 package com.android.inputmethod.latin;
 
+import com.android.inputmethod.latin.BaseKeyboardParser.ParseException;
+import com.android.inputmethod.latin.KeyStyles.KeyStyle;
 import com.android.inputmethod.latin.KeyboardSwitcher.KeyboardId;
 
 import org.xmlpull.v1.XmlPullParserException;
@@ -26,14 +28,11 @@ import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
-import android.util.Log;
-import android.util.TypedValue;
 import android.util.Xml;
 
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.StringTokenizer;
 
 /**
  * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard
@@ -284,7 +283,8 @@ public class BaseKeyboard {
          * @param y the y coordinate of the top-left
          * @param parser the XML parser containing the attributes for this key
          */
-        public Key(Resources res, Row parent, int x, int y, XmlResourceParser parser) {
+        public Key(Resources res, Row parent, int x, int y, XmlResourceParser parser,
+                KeyStyles keyStyles) {
             this(parent);
 
             TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
@@ -299,44 +299,47 @@ public class BaseKeyboard {
                     R.styleable.BaseKeyboard_keyWidth,
                     keyboard.mDisplayWidth, parent.defaultWidth) - gap;
             a.recycle();
+
             a = res.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.BaseKeyboard_Key);
 
+            final KeyStyle style;
+            if (a.hasValue(R.styleable.BaseKeyboard_Key_keyStyle)) {
+                String styleName = a.getString(R.styleable.BaseKeyboard_Key_keyStyle);
+                style = keyStyles.getKeyStyle(styleName);
+                if (style == null)
+                    throw new ParseException("Unknown key style: " + styleName, parser);
+            } else {
+                style = keyStyles.getEmptyKeyStyle();
+            }
+
             // Horizontal gap is divided equally to both sides of the key.
             this.x = x + gap / 2;
             this.y = y;
 
-            TypedValue codesValue = new TypedValue();
-            a.getValue(R.styleable.BaseKeyboard_Key_codes, codesValue);
-            if (codesValue.type == TypedValue.TYPE_INT_DEC
-                    || codesValue.type == TypedValue.TYPE_INT_HEX) {
-                codes = new int[] { codesValue.data };
-            } else if (codesValue.type == TypedValue.TYPE_STRING) {
-                codes = parseCSV(codesValue.string.toString());
-            }
-
-            iconPreview = a.getDrawable(R.styleable.BaseKeyboard_Key_iconPreview);
+            codes = style.getIntArray(a, R.styleable.BaseKeyboard_Key_codes);
+            iconPreview = style.getDrawable(a, R.styleable.BaseKeyboard_Key_iconPreview);
             setDefaultBounds(iconPreview);
-            popupCharacters = a.getText(R.styleable.BaseKeyboard_Key_popupCharacters);
-            popupResId = a.getResourceId(R.styleable.BaseKeyboard_Key_popupKeyboard, 0);
-            repeatable = a.getBoolean(R.styleable.BaseKeyboard_Key_isRepeatable, false);
-            modifier = a.getBoolean(R.styleable.BaseKeyboard_Key_isModifier, false);
-            sticky = a.getBoolean(R.styleable.BaseKeyboard_Key_isSticky, false);
-            edgeFlags = a.getInt(R.styleable.BaseKeyboard_Key_keyEdgeFlags, 0);
+            popupCharacters = style.getText(a, R.styleable.BaseKeyboard_Key_popupCharacters);
+            popupResId = style.getResourceId(a, R.styleable.BaseKeyboard_Key_popupKeyboard, 0);
+            repeatable = style.getBoolean(a, R.styleable.BaseKeyboard_Key_isRepeatable, false);
+            modifier = style.getBoolean(a, R.styleable.BaseKeyboard_Key_isModifier, false);
+            sticky = style.getBoolean(a, R.styleable.BaseKeyboard_Key_isSticky, false);
+            edgeFlags = style.getFlag(a, R.styleable.BaseKeyboard_Key_keyEdgeFlags, 0);
             edgeFlags |= parent.rowEdgeFlags;
 
-            icon = a.getDrawable(R.styleable.BaseKeyboard_Key_keyIcon);
+            icon = style.getDrawable(a, R.styleable.BaseKeyboard_Key_keyIcon);
             setDefaultBounds(icon);
-            hintIcon = a.getDrawable(R.styleable.BaseKeyboard_Key_keyHintIcon);
+            hintIcon = style.getDrawable(a, R.styleable.BaseKeyboard_Key_keyHintIcon);
             setDefaultBounds(hintIcon);
-            manualTemporaryUpperCaseHintIcon = a.getDrawable(
+            manualTemporaryUpperCaseHintIcon = style.getDrawable(a,
                     R.styleable.BaseKeyboard_Key_manualTemporaryUpperCaseHintIcon);
             setDefaultBounds(manualTemporaryUpperCaseHintIcon);
 
-            label = a.getText(R.styleable.BaseKeyboard_Key_keyLabel);
-            labelOption = a.getInt(R.styleable.BaseKeyboard_Key_keyLabelOption, 0);
-            manualTemporaryUpperCaseCode = a.getInt(
+            label = style.getText(a, R.styleable.BaseKeyboard_Key_keyLabel);
+            labelOption = style.getFlag(a, R.styleable.BaseKeyboard_Key_keyLabelOption, 0);
+            manualTemporaryUpperCaseCode = style.getInt(a,
                     R.styleable.BaseKeyboard_Key_manualTemporaryUpperCaseCode, 0);
-            text = a.getText(R.styleable.BaseKeyboard_Key_keyOutputText);
+            text = style.getText(a, R.styleable.BaseKeyboard_Key_keyOutputText);
 
             if (codes == null && !TextUtils.isEmpty(label)) {
                 codes = new int[] { label.charAt(0) };
@@ -366,28 +369,6 @@ public class BaseKeyboard {
             }
         }
 
-        private int[] parseCSV(String value) {
-            int count = 0;
-            int lastIndex = 0;
-            if (value.length() > 0) {
-                count++;
-                while ((lastIndex = value.indexOf(",", lastIndex + 1)) > 0) {
-                    count++;
-                }
-            }
-            int[] values = new int[count];
-            count = 0;
-            StringTokenizer st = new StringTokenizer(value, ",");
-            while (st.hasMoreTokens()) {
-                try {
-                    values[count++] = Integer.parseInt(st.nextToken());
-                } catch (NumberFormatException nfe) {
-                    Log.e(TAG, "Error parsing keycodes " + value);
-                }
-            }
-            return values;
-        }
-
         /**
          * Detects if a point falls inside this key.
          * @param x the x-coordinate of the point
@@ -560,6 +541,10 @@ public class BaseKeyboard {
         mTotalHeight = y + mDefaultHeight;
     }
 
+    public KeyboardId getKeyboardId() {
+        return mId;
+    }
+
     public List<Key> getKeys() {
         return mKeys;
     }
@@ -688,14 +673,15 @@ public class BaseKeyboard {
 
     // TODO should be private
     protected BaseKeyboard.Key createKeyFromXml(Resources res, Row parent, int x, int y,
-            XmlResourceParser parser) {
-        return new BaseKeyboard.Key(res, parent, x, y, parser);
+            XmlResourceParser parser, KeyStyles keyStyles) {
+        return new BaseKeyboard.Key(res, parent, x, y, parser, keyStyles);
     }
 
     private void loadKeyboard(Context context, int xmlLayoutResId) {
         try {
-            BaseKeyboardParser parser = new BaseKeyboardParser(this, context.getResources());
-            parser.parseKeyboard(context.getResources().getXml(xmlLayoutResId));
+            final Resources res = context.getResources();
+            BaseKeyboardParser parser = new BaseKeyboardParser(this, res);
+            parser.parseKeyboard(res.getXml(xmlLayoutResId));
             // mTotalWidth is the width of this keyboard which is maximum width of row.
             mTotalWidth = parser.getMaxRowWidth();
             mTotalHeight = parser.getTotalHeight();
diff --git a/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java b/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java
index 1aee2fcef01236e918d9605ddfdea856c48435cb..ea209c51530e54f420431f77b80a0e23fc6a49c6 100644
--- a/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java
+++ b/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java
@@ -83,27 +83,25 @@ import java.util.List;
  *     &gt;/default&lt;
  *   &gt;/switch&lt;
  * </pre>
- *
- * TODO: These are some random ideas to improve this parser.
- * - can specify keyWidth attribute by multiplication of default keyWidth
- *   for example: keyWidth="200%b" ("b" stands for "base")
- * - can declare style and specify styles within tags.
- *   for example:
+ * You can declare Key style and specify styles within Key tags.
+ * <pre>
  *     &gt;switch&lt;
  *       &gt;case colorScheme="white"&lt;
- *         &gt;declare-style name="shift-key" parentStyle="modifier-key"&lt;
- *           &gt;item name="keyIcon"&lt;@drawable/sym_keyboard_shift"&gt;/item&lt;
- *         &gt;/declare-style&lt;
+ *         &gt;key-style styleName="shift-key" parentStyle="modifier-key"
+ *           keyIcon="@drawable/sym_keyboard_shift"
+ *         /&lt;
  *       &gt;/case&lt;
  *       &gt;case colorScheme="black"&lt;
- *         &gt;declare-style name="shift-key" parentStyle="modifier-key"&lt;
- *           &gt;item name="keyIcon"&lt;@drawable/sym_bkeyboard_shift"&gt;/item&lt;
- *         &gt;/declare-style&lt;
+ *         &gt;key-style styleName="shift-key" parentStyle="modifier-key"
+ *           keyIcon="@drawable/sym_bkeyboard_shift"
+ *         /&lt;
  *       &gt;/case&lt;
  *     &gt;/switch&lt;
  *     ...
- *     &gt;Key include-style="shift-key" ... /&lt;
+ *     &gt;Key keyStyle="shift-key" ... /&lt;
+ * </pre>
  */
+
 public class BaseKeyboardParser {
     private static final String TAG = "BaseKeyboardParser";
     private static final boolean DEBUG_TAG = false;
@@ -118,6 +116,7 @@ public class BaseKeyboardParser {
     private static final String TAG_SWITCH = "switch";
     private static final String TAG_CASE = "case";
     private static final String TAG_DEFAULT = "default";
+    private static final String TAG_KEY_STYLE = "key-style";
 
     private final BaseKeyboard mKeyboard;
     private final Resources mResources;
@@ -127,6 +126,7 @@ public class BaseKeyboardParser {
     private int mMaxRowWidth = 0;
     private int mTotalHeight = 0;
     private Row mCurrentRow = null;
+    private final KeyStyles mKeyStyles = new KeyStyles();
 
     public BaseKeyboardParser(BaseKeyboard keyboard, Resources res) {
         mKeyboard = keyboard;
@@ -192,6 +192,8 @@ public class BaseKeyboardParser {
                     parseIncludeKeyboardContent(parser, keys);
                 } else if (TAG_SWITCH.equals(tag)) {
                     parseSwitchKeyboardContent(parser, keys);
+                } else if (TAG_KEY_STYLE.equals(tag)) {
+                    parseKeyStyle(parser, keys);
                 } else {
                     throw new IllegalStartTag(parser, TAG_ROW);
                 }
@@ -205,6 +207,8 @@ public class BaseKeyboardParser {
                     break;
                 } else if (TAG_MERGE.equals(tag)) {
                     break;
+                } else if (TAG_KEY_STYLE.equals(tag)) {
+                    continue;
                 } else {
                     throw new IllegalEndTag(parser, TAG_ROW);
                 }
@@ -227,6 +231,8 @@ public class BaseKeyboardParser {
                     parseIncludeRowContent(parser, row, keys);
                 } else if (TAG_SWITCH.equals(tag)) {
                     parseSwitchRowContent(parser, row, keys);
+                } else if (TAG_KEY_STYLE.equals(tag)) {
+                    parseKeyStyle(parser, keys);
                 } else {
                     throw new IllegalStartTag(parser, TAG_KEY);
                 }
@@ -241,6 +247,8 @@ public class BaseKeyboardParser {
                     break;
                 } else if (TAG_MERGE.equals(tag)) {
                     break;
+                } else if (TAG_KEY_STYLE.equals(tag)) {
+                    continue;
                 } else {
                     throw new IllegalEndTag(parser, TAG_KEY);
                 }
@@ -253,7 +261,8 @@ public class BaseKeyboardParser {
         if (keys == null) {
             checkEndTag(TAG_KEY, parser);
         } else {
-            Key key = mKeyboard.createKeyFromXml(mResources, row, mCurrentX, mCurrentY, parser);
+            Key key = mKeyboard.createKeyFromXml(mResources, row, mCurrentX, mCurrentY, parser,
+                    mKeyStyles);
             checkEndTag(TAG_KEY, parser);
             keys.add(key);
             if (key.codes[0] == BaseKeyboard.KEYCODE_SHIFT)
@@ -439,6 +448,24 @@ public class BaseKeyboardParser {
         return true;
     }
 
+    private void parseKeyStyle(XmlResourceParser parser, List<Key> keys)
+            throws XmlPullParserException, IOException {
+        TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+                R.styleable.BaseKeyboard_KeyStyle);
+        TypedArray keyAttrs = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+                R.styleable.BaseKeyboard_Key);
+        try {
+            if (!a.hasValue(R.styleable.BaseKeyboard_KeyStyle_styleName))
+                throw new ParseException("<" + TAG_KEY_STYLE
+                        + "/> needs styleName attribute", parser);
+            if (keys != null)
+                mKeyStyles.parseKeyStyleAttributes(a, keyAttrs, parser);
+        } finally {
+            a.recycle();
+            keyAttrs.recycle();
+        }
+    }
+
     private static void checkEndTag(String tag, XmlResourceParser parser)
             throws XmlPullParserException, IOException {
         if (parser.next() == XmlResourceParser.END_TAG && tag.equals(parser.getName()))
@@ -486,7 +513,7 @@ public class BaseKeyboardParser {
     }
 
     @SuppressWarnings("serial")
-    private static class ParseException extends InflateException {
+    public static class ParseException extends InflateException {
         public ParseException(String msg, XmlResourceParser parser) {
             super(msg + " at line " + parser.getLineNumber());
         }
diff --git a/java/src/com/android/inputmethod/latin/KeyStyles.java b/java/src/com/android/inputmethod/latin/KeyStyles.java
new file mode 100644
index 0000000000000000000000000000000000000000..e53e351a3c3c609d190bb8dbb8bc3ba13ccbd4fc
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/KeyStyles.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import com.android.inputmethod.latin.BaseKeyboardParser.ParseException;
+
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+import android.util.TypedValue;
+
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+public class KeyStyles {
+    private static final String TAG = "KeyStyles";
+
+    private final HashMap<String, DeclaredKeyStyle> mStyles =
+            new HashMap<String, DeclaredKeyStyle>();
+    private static final KeyStyle EMPTY_KEY_STYLE = new EmptyKeyStyle();
+
+    public interface KeyStyle {
+        public int[] getIntArray(TypedArray a, int index);
+        public Drawable getDrawable(TypedArray a, int index);
+        public CharSequence getText(TypedArray a, int index);
+        public int getResourceId(TypedArray a, int index, int defaultValue);
+        public int getInt(TypedArray a, int index, int defaultValue);
+        public int getFlag(TypedArray a, int index, int defaultValue);
+        public boolean getBoolean(TypedArray a, int index, boolean defaultValue);
+    }
+
+    public static class EmptyKeyStyle implements KeyStyle {
+        private EmptyKeyStyle() {
+        }
+
+        public int[] getIntArray(TypedArray a, int index) {
+            return parseIntArray(a, index);
+        }
+
+        public Drawable getDrawable(TypedArray a, int index) {
+            return a.getDrawable(index);
+        }
+
+        public CharSequence getText(TypedArray a, int index) {
+            return a.getText(index);
+        }
+
+        public int getResourceId(TypedArray a, int index, int defaultValue) {
+            return a.getResourceId(index, defaultValue);
+        }
+
+        public int getInt(TypedArray a, int index, int defaultValue) {
+            return a.getInt(index, defaultValue);
+        }
+
+        public int getFlag(TypedArray a, int index, int defaultValue) {
+            return a.getInt(index, defaultValue);
+        }
+
+        public boolean getBoolean(TypedArray a, int index, boolean defaultValue) {
+            return a.getBoolean(index, defaultValue);
+        }
+
+        protected static int[] parseIntArray(TypedArray a, int index) {
+            TypedValue v = new TypedValue();
+            a.getValue(index, v);
+            if (v.type == TypedValue.TYPE_INT_DEC || v.type == TypedValue.TYPE_INT_HEX) {
+                return new int[] { v.data };
+            } else if (v.type == TypedValue.TYPE_STRING) {
+                return parseCSV(v.string.toString());
+            } else {
+                return null;
+            }
+        }
+
+        private static int[] parseCSV(String value) {
+            int count = 0;
+            int lastIndex = 0;
+            if (value.length() > 0) {
+                count++;
+                while ((lastIndex = value.indexOf(",", lastIndex + 1)) > 0) {
+                    count++;
+                }
+            }
+            int[] values = new int[count];
+            count = 0;
+            StringTokenizer st = new StringTokenizer(value, ",");
+            while (st.hasMoreTokens()) {
+                try {
+                    values[count++] = Integer.parseInt(st.nextToken());
+                } catch (NumberFormatException nfe) {
+                    Log.e(TAG, "Error parsing integer CSV " + value);
+                }
+            }
+            return values;
+        }
+    }
+
+    public static class DeclaredKeyStyle extends EmptyKeyStyle {
+        private final HashMap<Integer, Object> mAttributes = new HashMap<Integer, Object>();
+
+        @Override
+        public int[] getIntArray(TypedArray a, int index) {
+            return a.hasValue(index)
+                    ? super.getIntArray(a, index) : (int[])mAttributes.get(index);
+        }
+
+        @Override
+        public Drawable getDrawable(TypedArray a, int index) {
+            return a.hasValue(index)
+                    ? super.getDrawable(a, index) : (Drawable)mAttributes.get(index);
+        }
+
+        @Override
+        public CharSequence getText(TypedArray a, int index) {
+            return a.hasValue(index)
+                    ? super.getText(a, index) : (CharSequence)mAttributes.get(index);
+        }
+
+        @Override
+        public int getResourceId(TypedArray a, int index, int defaultValue) {
+            final Integer value = (Integer)mAttributes.get(index);
+            return super.getResourceId(a, index, (value != null) ? value : defaultValue);
+        }
+
+        @Override
+        public int getFlag(TypedArray a, int index, int defaultValue) {
+            final Integer value = (Integer)mAttributes.get(index);
+            return super.getFlag(a, index, defaultValue) | (value != null ? value : 0);
+        }
+
+        @Override
+        public boolean getBoolean(TypedArray a, int index, boolean defaultValue) {
+            final Boolean value = (Boolean)mAttributes.get(index);
+            return super.getBoolean(a, index, (value != null) ? value : defaultValue);
+        }
+
+        private DeclaredKeyStyle() {
+            super();
+        }
+
+        private void parseKeyStyleAttributes(TypedArray a) {
+            // TODO: Currently not all Key attributes can be declared as style.
+            readIntArray(a, R.styleable.BaseKeyboard_Key_codes);
+            readText(a, R.styleable.BaseKeyboard_Key_keyLabel);
+            readFlag(a, R.styleable.BaseKeyboard_Key_keyLabelOption);
+            readText(a, R.styleable.BaseKeyboard_Key_keyOutputText);
+            readDrawable(a, R.styleable.BaseKeyboard_Key_keyIcon);
+            readDrawable(a, R.styleable.BaseKeyboard_Key_iconPreview);
+            readDrawable(a, R.styleable.BaseKeyboard_Key_keyHintIcon);
+            readResourceId(a, R.styleable.BaseKeyboard_Key_popupKeyboard);
+            readBoolean(a, R.styleable.BaseKeyboard_Key_isModifier);
+            readBoolean(a, R.styleable.BaseKeyboard_Key_isSticky);
+            readBoolean(a, R.styleable.BaseKeyboard_Key_isRepeatable);
+        }
+
+        private void readDrawable(TypedArray a, int index) {
+            if (a.hasValue(index))
+                mAttributes.put(index, a.getDrawable(index));
+        }
+
+        private void readText(TypedArray a, int index) {
+            if (a.hasValue(index))
+                mAttributes.put(index, a.getText(index));
+        }
+
+        private void readResourceId(TypedArray a, int index) {
+            if (a.hasValue(index))
+                mAttributes.put(index, a.getResourceId(index, 0));
+        }
+
+        private void readFlag(TypedArray a, int index) {
+            final Integer value = (Integer)mAttributes.get(index);
+            if (a.hasValue(index))
+                mAttributes.put(index, a.getInt(index, 0) | (value != null ? value : 0));
+        }
+
+        private void readBoolean(TypedArray a, int index) {
+            if (a.hasValue(index))
+                mAttributes.put(index, a.getBoolean(index, false));
+        }
+
+        private void readIntArray(TypedArray a, int index) {
+            if (a.hasValue(index)) {
+                final int[] value = parseIntArray(a, index);
+                if (value != null)
+                    mAttributes.put(index, value);
+            }
+        }
+
+        private void addParent(DeclaredKeyStyle parentStyle) {
+            mAttributes.putAll(parentStyle.mAttributes);
+        }
+    }
+
+    public void parseKeyStyleAttributes(TypedArray a, TypedArray keyAttrs,
+            XmlResourceParser parser) {
+        String styleName = a.getString(R.styleable.BaseKeyboard_KeyStyle_styleName);
+        if (mStyles.containsKey(styleName))
+            throw new ParseException("duplicate key style declared: " + styleName, parser);
+
+        final DeclaredKeyStyle style = new DeclaredKeyStyle();
+        if (a.hasValue(R.styleable.BaseKeyboard_KeyStyle_parentStyle)) {
+            String parentStyle = a.getString(
+                    R.styleable.BaseKeyboard_KeyStyle_parentStyle);
+            final DeclaredKeyStyle parent = mStyles.get(parentStyle);
+            if (parent == null)
+                throw new ParseException("Unknown parentStyle " + parent, parser);
+            style.addParent(parent);
+        }
+        style.parseKeyStyleAttributes(keyAttrs);
+        mStyles.put(styleName, style);
+    }
+
+    public KeyStyle getKeyStyle(String styleName) {
+        return mStyles.get(styleName);
+    }
+
+    public KeyStyle getEmptyKeyStyle() {
+        return EMPTY_KEY_STYLE;
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboard.java b/java/src/com/android/inputmethod/latin/LatinKeyboard.java
index 1242818d8a5232f093528d99880b5910694c4c4b..fc62053fe5d6c158fa5575809eb4fe18ef4f894e 100644
--- a/java/src/com/android/inputmethod/latin/LatinKeyboard.java
+++ b/java/src/com/android/inputmethod/latin/LatinKeyboard.java
@@ -127,8 +127,8 @@ public class LatinKeyboard extends BaseKeyboard {
 
     @Override
     protected Key createKeyFromXml(Resources res, Row parent, int x, int y, 
-            XmlResourceParser parser) {
-        Key key = new LatinKey(res, parent, x, y, parser);
+            XmlResourceParser parser, KeyStyles keyStyles) {
+        Key key = new LatinKey(res, parent, x, y, parser, keyStyles);
         switch (key.codes[0]) {
         case LatinIME.KEYCODE_ENTER:
             mEnterKey = key;
@@ -619,8 +619,8 @@ public class LatinKeyboard extends BaseKeyboard {
         private boolean mShiftLockEnabled;
 
         public LatinKey(Resources res, BaseKeyboard.Row parent, int x, int y,
-                XmlResourceParser parser) {
-            super(res, parent, x, y, parser);
+                XmlResourceParser parser, KeyStyles keyStyles) {
+            super(res, parent, x, y, parser, keyStyles);
             if (popupCharacters != null && popupCharacters.length() == 0) {
                 // If there is a keyboard with no keys specified in popupCharacters
                 popupResId = 0;