Merge "Some renaming"
diff --git a/java/Android.mk b/java/Android.mk
index fd71d82..52cc18b 100644
--- a/java/Android.mk
+++ b/java/Android.mk
@@ -30,6 +30,7 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := android-common
 LOCAL_STATIC_JAVA_LIBRARIES += inputmethod-common
+LOCAL_STATIC_JAVA_LIBRARIES += android-support-v4
 
 # Do not compress dictionary files to mmap dict data runtime
 LOCAL_AAPT_FLAGS := -0 .dict
diff --git a/java/res/drawable-hdpi/more_keys_divider.png b/java/res/drawable-hdpi/more_keys_divider.png
new file mode 100644
index 0000000..a5912f9
--- /dev/null
+++ b/java/res/drawable-hdpi/more_keys_divider.png
Binary files differ
diff --git a/java/res/drawable-mdpi/more_keys_divider.png b/java/res/drawable-mdpi/more_keys_divider.png
new file mode 100644
index 0000000..a46284f
--- /dev/null
+++ b/java/res/drawable-mdpi/more_keys_divider.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/more_keys_divider.png b/java/res/drawable-xhdpi/more_keys_divider.png
new file mode 100644
index 0000000..178594b
--- /dev/null
+++ b/java/res/drawable-xhdpi/more_keys_divider.png
Binary files differ
diff --git a/java/res/values-be/donottranslate-more-keys.xml b/java/res/values-be/donottranslate-more-keys.xml
index 0917f11..1550ddb 100644
--- a/java/res/values-be/donottranslate-more-keys.xml
+++ b/java/res/values-be/donottranslate-more-keys.xml
@@ -19,7 +19,7 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- U+045E: "ў" CYRILLIC SMALL LETTER SHORT U -->
-    <string name="keylabel_for_slavic_shcha">&#x045E;</string>
+    <string name="keylabel_for_cyrillic_shcha">&#x045E;</string>
     <!-- U+0456: "і" CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I -->
-    <string name="keylabel_for_slavic_i">&#x0456;</string>
+    <string name="keylabel_for_cyrillic_i">&#x0456;</string>
 </resources>
diff --git a/java/res/values-ky/donottranslate-more-keys.xml b/java/res/values-ky/donottranslate-more-keys.xml
index 8246209..b67a9f1 100644
--- a/java/res/values-ky/donottranslate-more-keys.xml
+++ b/java/res/values-ky/donottranslate-more-keys.xml
@@ -19,9 +19,9 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- U+04AF: "ү" CYRILLIC SMALL LETTER STRAIGHT U -->
-    <string name="more_keys_for_slavic_u">&#x04AF;</string>
+    <string name="more_keys_for_cyrillic_u">&#x04AF;</string>
     <!-- U+04A3: "ң" CYRILLIC SMALL LETTER EN WITH DESCENDER -->
-    <string name="more_keys_for_slavic_en">&#x04A3;</string>
+    <string name="more_keys_for_cyrillic_en">&#x04A3;</string>
     <!-- U+04E9: "ө" CYRILLIC SMALL LETTER BARRED O -->
-    <string name="more_keys_for_slavic_o">&#x04E9;</string>
+    <string name="more_keys_for_cyrillic_o">&#x04E9;</string>
 </resources>
diff --git a/java/res/values-mk/donottranslate-more-keys.xml b/java/res/values-mk/donottranslate-more-keys.xml
new file mode 100644
index 0000000..e96a306
--- /dev/null
+++ b/java/res/values-mk/donottranslate-more-keys.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- NOTE: Macedonian layouts are based on Serbian ones with the following key replacements. -->
+    <!-- U+0455: "ѕ" CYRILLIC SMALL LETTER DZE -->
+    <string name="keylabel_for_cyrillic_ze">&#x0455;</string>
+    <!-- U+045C: "ќ" CYRILLIC SMALL LETTER KJE -->
+    <string name="keylabel_for_cyrillic_tshe">&#x045C;</string>
+    <!-- U+0437: "з" CYRILLIC SMALL LETTER ZE -->
+    <string name="keylabel_for_cyrillic_dze">&#x0437;</string>
+    <!-- U+0453: "ѓ" CYRILLIC SMALL LETTER GJE -->
+    <string name="keylabel_for_cyrillic_dje">&#x0453;</string>
+    <!-- U+0450: "ѐ" CYRILLIC SMALL LETTER IE WITH GRAVE -->
+    <string name="more_keys_for_cyrillic_ie">&#x0450;</string>
+    <!-- U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE -->
+    <string name="more_keys_for_cyrillic_i">&#x045D;</string>
+    <!-- U+2018: "‘" LEFT SINGLE QUOTATION MARK
+         U+2019: "’" RIGHT SINGLE QUOTATION MARK
+         U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+         U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK
+         U+201C: "“" LEFT DOUBLE QUOTATION MARK
+         U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+         U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+         U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK -->
+    <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. -->
+    <!-- <string name="more_keys_for_double_quote">!fixedColumnOrder!6,&#x201E;,&#x201C;,&#x201D;,&#x201F;,&#x00AB;,&#x00BB;</string> -->
+    <string name="more_keys_for_double_quote">!fixedColumnOrder!5,&#x201E;,&#x201C;,&#x201D;,&#x00AB;,&#x00BB;</string>
+    <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. -->
+    <!-- <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string> -->
+    <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!5,&#x201E;,&#x201C;,&#x201D;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
+</resources>
diff --git a/java/res/values-ru/donottranslate-more-keys.xml b/java/res/values-ru/donottranslate-more-keys.xml
index 45c4551..a1a22e5 100644
--- a/java/res/values-ru/donottranslate-more-keys.xml
+++ b/java/res/values-ru/donottranslate-more-keys.xml
@@ -19,5 +19,5 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- U+0451: "ё" CYRILLIC SMALL LETTER IO -->
-    <string name="more_keys_for_slavic_ye">&#x0451;</string>
+    <string name="more_keys_for_cyrillic_ye">&#x0451;</string>
 </resources>
diff --git a/java/res/values-uk/donottranslate-more-keys.xml b/java/res/values-uk/donottranslate-more-keys.xml
index 3208a66..323eaaf 100644
--- a/java/res/values-uk/donottranslate-more-keys.xml
+++ b/java/res/values-uk/donottranslate-more-keys.xml
@@ -19,7 +19,7 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- U+0456: "і" CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I -->
-    <string name="keylabel_for_slavic_yery">&#x0456;</string>
+    <string name="keylabel_for_cyrillic_yery">&#x0456;</string>
     <!-- U+0457: "ї" CYRILLIC SMALL LETTER YI -->
-    <string name="more_keys_for_slavic_yery">&#x0457;</string>
+    <string name="more_keys_for_cyrillic_yery">&#x0457;</string>
 </resources>
diff --git a/java/res/values/donottranslate-more-keys.xml b/java/res/values/donottranslate-more-keys.xml
index afce245..6577acd 100644
--- a/java/res/values/donottranslate-more-keys.xml
+++ b/java/res/values/donottranslate-more-keys.xml
@@ -41,20 +41,30 @@
     <string name="more_keys_for_scandinavia_row2_10"></string>
     <string name="more_keys_for_scandinavia_row2_11"></string>
     <!-- U+0449: "щ" CYRILLIC SMALL LETTER SHCHA -->
-    <string name="keylabel_for_slavic_shcha">&#x0449;</string>
+    <string name="keylabel_for_cyrillic_shcha">&#x0449;</string>
     <!-- U+044B: "ы" CYRILLIC SMALL LETTER YERU -->
-    <string name="keylabel_for_slavic_yery">&#x044B;</string>
+    <string name="keylabel_for_cyrillic_yery">&#x044B;</string>
     <!-- U+0438: "и" CYRILLIC SMALL LETTER I -->
-    <string name="keylabel_for_slavic_i">&#x0438;</string>
-    <string name="more_keys_for_slavic_u"></string>
-    <string name="more_keys_for_slavic_ye"></string>
-    <string name="more_keys_for_slavic_en"></string>
+    <string name="keylabel_for_cyrillic_i">&#x0438;</string>
+    <!-- U+0437: "з" CYRILLIC SMALL LETTER ZE -->
+    <string name="keylabel_for_cyrillic_ze">&#x0437;</string>
+    <!-- U+045B: "ћ" CYRILLIC SMALL LETTER TSHE -->
+    <string name="keylabel_for_cyrillic_tshe">&#x045B;</string>
+    <!-- U+0455: "ѕ" CYRILLIC SMALL LETTER DZE -->
+    <string name="keylabel_for_cyrillic_dze">&#x0455;</string>
+    <!-- U+0452: "ђ" CYRILLIC SMALL LETTER DJE -->
+    <string name="keylabel_for_cyrillic_dje">&#x0452;</string>
+    <string name="more_keys_for_cyrillic_u"></string>
+    <string name="more_keys_for_cyrillic_ye"></string>
+    <string name="more_keys_for_cyrillic_en"></string>
     <!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN -->
-    <string name="more_keys_for_slavic_ha">&#x044A;</string>
-    <string name="more_keys_for_slavic_yery"></string>
-    <string name="more_keys_for_slavic_o"></string>
+    <string name="more_keys_for_cyrillic_ha">&#x044A;</string>
+    <string name="more_keys_for_cyrillic_yery"></string>
+    <string name="more_keys_for_cyrillic_o"></string>
     <!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN -->
-    <string name="more_keys_for_slavic_soft_sign">&#x044A;</string>
+    <string name="more_keys_for_cyrillic_soft_sign">&#x044A;</string>
+    <string name="more_keys_for_cyrillic_ie"></string>
+    <string name="more_keys_for_cyrillic_i"></string>
     <!-- U+00A2: "¢" CENT SIGN
          U+00A3: "£" POUND SIGN
          U+20AC: "€" EURO SIGN
diff --git a/java/res/xml-el/keyboard_set.xml b/java/res/xml-el/keyboard_set.xml
new file mode 100644
index 0000000..19ecb77
--- /dev/null
+++ b/java/res/xml-el/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, 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.
+*/
+-->
+
+<KeyboardSet
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+    latin:keyboardLocale="el">
+    <Element
+        latin:elementName="alphabet"
+        latin:elementKeyboard="@xml/kbd_greek" />
+    <Element
+        latin:elementName="symbols"
+        latin:elementKeyboard="@xml/kbd_symbols" />
+    <Element
+        latin:elementName="symbolsShifted"
+        latin:elementKeyboard="@xml/kbd_symbols_shift" />
+    <Element
+        latin:elementName="phone"
+        latin:elementKeyboard="@xml/kbd_phone" />
+    <Element
+        latin:elementName="phoneSymbols"
+        latin:elementKeyboard="@xml/kbd_phone_symbols" />
+    <Element
+        latin:elementName="number"
+        latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-mk/keyboard_set.xml b/java/res/xml-mk/keyboard_set.xml
new file mode 100644
index 0000000..31199cb
--- /dev/null
+++ b/java/res/xml-mk/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, 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.
+*/
+-->
+
+<KeyboardSet
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+    latin:keyboardLocale="mk">
+    <Element
+        latin:elementName="alphabet"
+        latin:elementKeyboard="@xml/kbd_serbian" />
+    <Element
+        latin:elementName="symbols"
+        latin:elementKeyboard="@xml/kbd_symbols" />
+    <Element
+        latin:elementName="symbolsShifted"
+        latin:elementKeyboard="@xml/kbd_symbols_shift" />
+    <Element
+        latin:elementName="phone"
+        latin:elementKeyboard="@xml/kbd_phone" />
+    <Element
+        latin:elementName="phoneSymbols"
+        latin:elementKeyboard="@xml/kbd_phone_symbols" />
+    <Element
+        latin:elementName="number"
+        latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-sw600dp/rows_greek.xml b/java/res/xml-sw600dp/rows_greek.xml
new file mode 100644
index 0000000..c77627e
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_greek.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, 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"
+>
+    <include
+        latin:keyboardLayout="@xml/key_styles_common" />
+    <Row
+        latin:keyWidth="9.0%p"
+    >
+        <Key
+            latin:keyLabel=";" />
+        <!-- TODO: Should find a way to compound Greek dialytika tonos and other Greek letters. -->
+        <!--
+        <switch>
+            <case
+                latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+            >
+                U+0385: "΅" GREEK DIALYTIKA TONOS
+                <Key
+                    latin:keyLabel="&#x0385;" />
+            </case>
+            <default>
+        -->
+                <!-- U+03C2: "ς" GREEK SMALL LETTER FINAL SIGMA -->
+                <Key
+                    latin:keyLabel="&#x03C2;"
+                    latin:keyLabelFlags="preserveCase" />
+        <!--
+            </default>
+        </switch>
+        -->
+        <!-- U+03B5: "ε" GREEK SMALL LETTER EPSILON
+             U+03AD: "έ" GREEK SMALL LETTER EPSILON WITH TONOS -->
+        <Key
+            latin:keyLabel="&#x03B5;"
+            latin:moreKeys="&#x03AD;" />
+        <!-- U+03C1: "ρ" GREEK SMALL LETTER RHO -->
+        <Key
+            latin:keyLabel="&#x03C1;" />
+        <!-- U+03C4: "τ" GREEK SMALL LETTER TAU -->
+        <Key
+            latin:keyLabel="&#x03C4;" />
+        <!-- U+03C5: "υ" GREEK SMALL LETTER UPSILON
+             U+03CD: "ύ" GREEK SMALL LETTER UPSILON WITH TONOS
+             U+03CB: "ϋ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+             U+03B0: "ΰ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS -->
+        <Key
+            latin:keyLabel="&#x03C5;"
+            latin:moreKeys="&#x03CD;,&#x03CB;,&#x03B0;" />
+        <!-- U+03B8: "θ" GREEK SMALL LETTER THETA -->
+        <Key
+            latin:keyLabel="&#x03B8;" />
+        <!-- U+03B9: "ι" GREEK SMALL LETTER IOTA
+             U+03AF: "ί" GREEK SMALL LETTER IOTA WITH TONOS
+             U+03CA: "ϊ" GREEK SMALL LETTER IOTA WITH DIALYTIKA
+             U+0390: "ΐ" GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS -->
+        <Key
+            latin:keyLabel="&#x03B9;"
+            latin:moreKeys="&#x03AF;,&#x03CA;,&#x0390;" />
+        <!-- U+03BF: "ο" GREEK SMALL LETTER OMICRON
+             U+03CC: "ό" GREEK SMALL LETTER OMICRON WITH TONOS -->
+        <Key
+            latin:keyLabel="&#x03BF;"
+            latin:moreKeys="&#x03CC;" />
+        <!-- U+03C0: "π" GREEK SMALL LETTER PI -->
+        <Key
+            latin:keyLabel="&#x03C0;" />
+        <Key
+            latin:keyStyle="deleteKeyStyle"
+            latin:keyXPos="-10.0%p"
+            latin:keyWidth="fillBoth" />
+    </Row>
+    <Row
+        latin:keyWidth="9.0%p"
+    >
+        <!-- U+03B1: "α" GREEK SMALL LETTER ALPHA
+             U+03AC: "ά" GREEK SMALL LETTER ALPHA WITH TONOS -->
+        <Key
+            latin:keyLabel="&#x03B1;"
+            latin:moreKeys="&#x03AC;"
+            latin:keyXPos="4.5%p" />
+        <!-- U+03C3: "σ" GREEK SMALL LETTER SIGMA -->
+        <Key
+            latin:keyLabel="&#x03C3;" />
+        <!-- U+03B4: "δ" GREEK SMALL LETTER DELTA -->
+        <Key
+            latin:keyLabel="&#x03B4;" />
+        <!-- U+03C6: "φ" GREEK SMALL LETTER PHI -->
+        <Key
+            latin:keyLabel="&#x03C6;" />
+        <!-- U+03B3: "γ" GREEK SMALL LETTER GAMMA -->
+        <Key
+            latin:keyLabel="&#x03B3;" />
+        <!-- U+03B7: "η" GREEK SMALL LETTER ETA
+             U+03AE: "ή" GREEK SMALL LETTER ETA WITH TONOS -->
+        <Key
+            latin:keyLabel="&#x03B7;"
+            latin:moreKeys="&#x03AE;" />
+        <!-- U+03BE: "ξ" GREEK SMALL LETTER XI -->
+        <Key
+            latin:keyLabel="&#x03BE;" />
+        <!-- U+03BA: "κ" GREEK SMALL LETTER KAPPA -->
+        <Key
+            latin:keyLabel="&#x03BA;" />
+        <!-- U+03BB: "λ" GREEK SMALL LETTER LAMDA -->
+        <Key
+            latin:keyLabel="&#x03BB;" />
+        <Key
+            latin:keyStyle="enterKeyStyle"
+            latin:keyXPos="-14.6%p"
+            latin:keyWidth="fillBoth" />
+    </Row>
+    <Row
+        latin:keyWidth="8.9%p"
+    >
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="10.0%p" />
+        <!-- U+03B6: "ζ" GREEK SMALL LETTER ZETA -->
+        <Key
+            latin:keyLabel="&#x03B6;" />
+        <!-- U+03C7: "χ" GREEK SMALL LETTER CHI -->
+        <Key
+            latin:keyLabel="&#x03C7;" />
+        <!-- U+03C8: "ψ" GREEK SMALL LETTER PSI -->
+        <Key
+            latin:keyLabel="&#x03C8;" />
+        <!-- U+03C9: "ω" GREEK SMALL LETTER OMEGA
+             U+03CE: "ώ" GREEK SMALL LETTER OMEGA WITH TONOS -->
+        <Key
+            latin:keyLabel="&#x03C9;"
+            latin:moreKeys="&#x03CE;" />
+        <!-- U+03B2: "β" GREEK SMALL LETTER BETA -->
+        <Key
+            latin:keyLabel="&#x03B2;" />
+        <!-- U+03BD: "ν" GREEK SMALL LETTER NU -->
+        <Key
+            latin:keyLabel="&#x03BD;" />
+        <!-- U+03BC: "μ" GREEK SMALL LETTER MU -->
+        <Key
+            latin:keyLabel="&#x03BC;" />
+        <include
+            latin:keyboardLayout="@xml/keys_comma_period" />
+        <include
+            latin:keyboardLayout="@xml/key_smiley"
+            latin:keyXPos="-8.9%p"
+            latin:keyWidth="fillBoth" />
+    </Row>
+    <include
+        latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_serbian.xml b/java/res/xml-sw600dp/rows_serbian.xml
index 5730aa0..989fa48 100644
--- a/java/res/xml-sw600dp/rows_serbian.xml
+++ b/java/res/xml-sw600dp/rows_serbian.xml
@@ -35,22 +35,23 @@
             latin:keyLabel="&#x045A;" />
         <!-- U+0435: "е" CYRILLIC SMALL LETTER IE -->
         <Key
-            latin:keyLabel="&#x0435;" />
+            latin:keyLabel="&#x0435;"
+            latin:moreKeys="@string/more_keys_for_cyrillic_ie" />
         <!-- U+0440: "р" CYRILLIC SMALL LETTER ER -->
         <Key
             latin:keyLabel="&#x0440;" />
         <!-- U+0442: "т" CYRILLIC SMALL LETTER TE -->
         <Key
             latin:keyLabel="&#x0442;" />
-        <!-- U+0437: "з" CYRILLIC SMALL LETTER ZE -->
         <Key
-            latin:keyLabel="&#x0437;" />
+            latin:keyLabel="@string/keylabel_for_cyrillic_ze" />
         <!-- U+0443: "у" CYRILLIC SMALL LETTER U -->
         <Key
             latin:keyLabel="&#x0443;" />
         <!-- U+0438: "и" CYRILLIC SMALL LETTER I -->
         <Key
-            latin:keyLabel="&#x0438;" />
+            latin:keyLabel="&#x0438;"
+            latin:moreKeys="@string/more_keys_for_cyrillic_i" />
         <!-- U+043E: "о" CYRILLIC SMALL LETTER O -->
         <Key
             latin:keyLabel="&#x043E;" />
@@ -98,9 +99,8 @@
         <!-- U+0447: "ч" CYRILLIC SMALL LETTER CHE -->
         <Key
             latin:keyLabel="&#x0447;" />
-        <!-- U+045B: "ћ" CYRILLIC SMALL LETTER TSHE -->
         <Key
-            latin:keyLabel="&#x045B;" />
+            latin:keyLabel="@string/keylabel_for_cyrillic_tshe" />
         <Key
             latin:keyStyle="enterKeyStyle"
             latin:keyXPos="-14.6%p"
@@ -112,9 +112,8 @@
         <Key
             latin:keyStyle="shiftKeyStyle"
             latin:keyWidth="8.0%p" />
-        <!-- U+0455: "ѕ" CYRILLIC SMALL LETTER DZE -->
         <Key
-            latin:keyLabel="&#x0455;" />
+            latin:keyLabel="@string/keylabel_for_cyrillic_dze" />
         <!-- U+045F: "џ" CYRILLIC SMALL LETTER DZHE -->
         <Key
             latin:keyLabel="&#x045F;" />
@@ -133,9 +132,8 @@
         <!-- U+043C: "м" CYRILLIC SMALL LETTER EM -->
         <Key
             latin:keyLabel="&#x043C;" />
-        <!-- U+0452: "ђ" CYRILLIC SMALL LETTER DJE -->
         <Key
-            latin:keyLabel="&#x0452;" />
+            latin:keyLabel="@string/keylabel_for_cyrillic_dje" />
         <!-- U+0436: "ж" CYRILLIC SMALL LETTER ZHE -->
         <Key
             latin:keyLabel="&#x0436;" />
diff --git a/java/res/xml-sw600dp/rows_slavic.xml b/java/res/xml-sw600dp/rows_slavic.xml
index 58f0b39..7ff63bc 100644
--- a/java/res/xml-sw600dp/rows_slavic.xml
+++ b/java/res/xml-sw600dp/rows_slavic.xml
@@ -35,18 +35,18 @@
         <!-- U+0443: "у" CYRILLIC SMALL LETTER U -->
         <Key
             latin:keyLabel="&#x0443;"
-            latin:moreKeys="@string/more_keys_for_slavic_u" />
+            latin:moreKeys="@string/more_keys_for_cyrillic_u" />
         <!-- U+043A: "к" CYRILLIC SMALL LETTER KA -->
         <Key
             latin:keyLabel="&#x043A;" />
         <!-- U+0435: "е" CYRILLIC SMALL LETTER IE -->
         <Key
             latin:keyLabel="&#x0435;"
-            latin:moreKeys="@string/more_keys_for_slavic_ye" />
+            latin:moreKeys="@string/more_keys_for_cyrillic_ye" />
         <!-- U+043D: "н" CYRILLIC SMALL LETTER EN -->
         <Key
             latin:keyLabel="&#x043D;"
-            latin:moreKeys="@string/more_keys_for_slavic_en" />
+            latin:moreKeys="@string/more_keys_for_cyrillic_en" />
         <!-- U+0433: "г" CYRILLIC SMALL LETTER GHE -->
         <Key
             latin:keyLabel="&#x0433;" />
@@ -54,7 +54,7 @@
         <Key
             latin:keyLabel="&#x0448;" />
         <Key
-            latin:keyLabel="@string/keylabel_for_slavic_shcha" />
+            latin:keyLabel="@string/keylabel_for_cyrillic_shcha" />
         <!-- U+0437: "з" CYRILLIC SMALL LETTER ZE -->
         <Key
             latin:keyLabel="&#x0437;" />
@@ -77,8 +77,8 @@
             latin:keyLabel="&#x0444;"
             latin:keyXPos="2.25%p" />
         <Key
-            latin:keyLabel="@string/keylabel_for_slavic_yery"
-            latin:moreKeys="@string/more_keys_for_slavic_yery" />
+            latin:keyLabel="@string/keylabel_for_cyrillic_yery"
+            latin:moreKeys="@string/more_keys_for_cyrillic_yery" />
         <!-- U+0432: "в" CYRILLIC SMALL LETTER VE -->
         <Key
             latin:keyLabel="&#x0432;" />
@@ -94,7 +94,7 @@
         <!-- U+043E: "о" CYRILLIC SMALL LETTER O -->
         <Key
             latin:keyLabel="&#x043E;"
-            latin:moreKeys="@string/more_keys_for_slavic_o" />
+            latin:moreKeys="@string/more_keys_for_cyrillic_o" />
         <!-- U+043B: "л" CYRILLIC SMALL LETTER EL -->
         <Key
             latin:keyLabel="&#x043B;" />
@@ -130,7 +130,7 @@
         <Key
             latin:keyLabel="&#x043C;" />
         <Key
-            latin:keyLabel="@string/keylabel_for_slavic_i" />
+            latin:keyLabel="@string/keylabel_for_cyrillic_i" />
         <!-- U+0442: "т" CYRILLIC SMALL LETTER TE -->
         <Key
             latin:keyLabel="&#x0442;" />
diff --git a/java/res/xml-sw768dp/rows_greek.xml b/java/res/xml-sw768dp/rows_greek.xml
new file mode 100644
index 0000000..e9a76a5
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_greek.xml
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, 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"
+>
+    <include
+        latin:keyboardLayout="@xml/key_styles_common" />
+    <Row
+        latin:keyWidth="8.282%p"
+    >
+        <Key
+            latin:keyStyle="tabKeyStyle"
+            latin:keyLabelFlags="alignLeft"
+            latin:keyWidth="7.969%p" />
+        <Key
+            latin:keyLabel=";" />
+        <!-- TODO: Should find a way to compound Greek dialytika tonos and other Greek letters. -->
+        <!--
+        <switch>
+            <case
+                latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+            >
+                U+0385: "΅" GREEK DIALYTIKA TONOS
+                <Key
+                    latin:keyLabel="&#x0385;" />
+            </case>
+            <default>
+        -->
+                <!-- U+03C2: "ς" GREEK SMALL LETTER FINAL SIGMA -->
+                <Key
+                    latin:keyLabel="&#x03C2;"
+                    latin:keyLabelFlags="preserveCase" />
+        <!--
+            </default>
+        </switch>
+        -->
+        <!-- U+03B5: "ε" GREEK SMALL LETTER EPSILON
+             U+03AD: "έ" GREEK SMALL LETTER EPSILON WITH TONOS -->
+        <Key
+            latin:keyLabel="&#x03B5;"
+            latin:moreKeys="&#x03AD;" />
+        <!-- U+03C1: "ρ" GREEK SMALL LETTER RHO -->
+        <Key
+            latin:keyLabel="&#x03C1;" />
+        <!-- U+03C4: "τ" GREEK SMALL LETTER TAU -->
+        <Key
+            latin:keyLabel="&#x03C4;" />
+        <!-- U+03C5: "υ" GREEK SMALL LETTER UPSILON
+             U+03CD: "ύ" GREEK SMALL LETTER UPSILON WITH TONOS
+             U+03CB: "ϋ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+             U+03B0: "ΰ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS -->
+        <Key
+            latin:keyLabel="&#x03C5;"
+            latin:moreKeys="&#x03CD;,&#x03CB;,&#x03B0;" />
+        <!-- U+03B8: "θ" GREEK SMALL LETTER THETA -->
+        <Key
+            latin:keyLabel="&#x03B8;" />
+        <!-- U+03B9: "ι" GREEK SMALL LETTER IOTA
+             U+03AF: "ί" GREEK SMALL LETTER IOTA WITH TONOS
+             U+03CA: "ϊ" GREEK SMALL LETTER IOTA WITH DIALYTIKA
+             U+0390: "ΐ" GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS -->
+        <Key
+            latin:keyLabel="&#x03B9;"
+            latin:moreKeys="&#x03AF;,&#x03CA;,&#x0390;" />
+        <!-- U+03BF: "ο" GREEK SMALL LETTER OMICRON
+             U+03CC: "ό" GREEK SMALL LETTER OMICRON WITH TONOS -->
+        <Key
+            latin:keyLabel="&#x03BF;"
+            latin:moreKeys="&#x03CC;" />
+        <!-- U+03C0: "π" GREEK SMALL LETTER PI -->
+        <Key
+            latin:keyLabel="&#x03C0;" />
+        <Key
+            latin:keyStyle="deleteKeyStyle"
+            latin:keyXPos="-9.219%p"
+            latin:keyWidth="fillBoth" />
+    </Row>
+    <Row
+        latin:keyWidth="8.125%p"
+    >
+        <Key
+            latin:keyStyle="toSymbolKeyStyle"
+            latin:keyLabelFlags="alignLeft"
+            latin:keyWidth="11.172%p"/>
+        <!-- U+03B1: "α" GREEK SMALL LETTER ALPHA
+             U+03AC: "ά" GREEK SMALL LETTER ALPHA WITH TONOS -->
+        <Key
+            latin:keyLabel="&#x03B1;"
+            latin:moreKeys="&#x03AC;" />
+        <!-- U+03C3: "σ" GREEK SMALL LETTER SIGMA -->
+        <Key
+            latin:keyLabel="&#x03C3;" />
+        <!-- U+03B4: "δ" GREEK SMALL LETTER DELTA -->
+        <Key
+            latin:keyLabel="&#x03B4;" />
+        <!-- U+03C6: "φ" GREEK SMALL LETTER PHI -->
+        <Key
+            latin:keyLabel="&#x03C6;" />
+        <!-- U+03B3: "γ" GREEK SMALL LETTER GAMMA -->
+        <Key
+            latin:keyLabel="&#x03B3;" />
+        <!-- U+03B7: "η" GREEK SMALL LETTER ETA
+             U+03AE: "ή" GREEK SMALL LETTER ETA WITH TONOS -->
+        <Key
+            latin:keyLabel="&#x03B7;"
+            latin:moreKeys="&#x03AE;" />
+        <!-- U+03BE: "ξ" GREEK SMALL LETTER XI -->
+        <Key
+            latin:keyLabel="&#x03BE;" />
+        <!-- U+03BA: "κ" GREEK SMALL LETTER KAPPA -->
+        <Key
+            latin:keyLabel="&#x03BA;" />
+        <!-- U+03BB: "λ" GREEK SMALL LETTER LAMDA -->
+        <Key
+            latin:keyLabel="&#x03BB;" />
+        <Key
+            latin:keyStyle="enterKeyStyle"
+            latin:keyXPos="-15.704%p"
+            latin:keyWidth="fillBoth" />
+    </Row>
+    <Row
+        latin:keyWidth="8.047%p"
+    >
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="13.829%p" />
+        <!-- U+03B6: "ζ" GREEK SMALL LETTER ZETA -->
+        <Key
+            latin:keyLabel="&#x03B6;" />
+        <!-- U+03C7: "χ" GREEK SMALL LETTER CHI -->
+        <Key
+            latin:keyLabel="&#x03C7;" />
+        <!-- U+03C8: "ψ" GREEK SMALL LETTER PSI -->
+        <Key
+            latin:keyLabel="&#x03C8;" />
+        <!-- U+03C9: "ω" GREEK SMALL LETTER OMEGA
+             U+03CE: "ώ" GREEK SMALL LETTER OMEGA WITH TONOS -->
+        <Key
+            latin:keyLabel="&#x03C9;"
+            latin:moreKeys="&#x03CE;" />
+        <!-- U+03B2: "β" GREEK SMALL LETTER BETA -->
+        <Key
+            latin:keyLabel="&#x03B2;" />
+        <!-- U+03BD: "ν" GREEK SMALL LETTER NU -->
+        <Key
+            latin:keyLabel="&#x03BD;" />
+        <!-- U+03BC: "μ" GREEK SMALL LETTER MU -->
+        <Key
+            latin:keyLabel="&#x03BC;" />
+        <include
+            latin:keyboardLayout="@xml/keys_comma_period" />
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyXPos="-13.750%p"
+            latin:keyWidth="fillBoth" />
+    </Row>
+   <include
+        latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_serbian.xml b/java/res/xml-sw768dp/rows_serbian.xml
index 39907c8..62668e5 100644
--- a/java/res/xml-sw768dp/rows_serbian.xml
+++ b/java/res/xml-sw768dp/rows_serbian.xml
@@ -37,22 +37,23 @@
             latin:keyLabel="&#x045A;" />
         <!-- U+0435: "е" CYRILLIC SMALL LETTER IE -->
         <Key
-            latin:keyLabel="&#x0435;" />
+            latin:keyLabel="&#x0435;"
+            latin:moreKeys="@string/more_keys_for_cyrillic_ie" />
         <!-- U+0440: "р" CYRILLIC SMALL LETTER ER -->
         <Key
             latin:keyLabel="&#x0440;" />
         <!-- U+0442: "т" CYRILLIC SMALL LETTER TE -->
         <Key
             latin:keyLabel="&#x0442;" />
-        <!-- U+0437: "з" CYRILLIC SMALL LETTER ZE -->
         <Key
-            latin:keyLabel="&#x0437;" />
+            latin:keyLabel="@string/keylabel_for_cyrillic_ze" />
         <!-- U+0443: "у" CYRILLIC SMALL LETTER U -->
         <Key
             latin:keyLabel="&#x0443;" />
         <!-- U+0438: "и" CYRILLIC SMALL LETTER I -->
         <Key
-            latin:keyLabel="&#x0438;" />
+            latin:keyLabel="&#x0438;"
+            latin:moreKeys="@string/more_keys_for_cyrillic_i" />
         <!-- U+043E: "о" CYRILLIC SMALL LETTER O -->
         <Key
             latin:keyLabel="&#x043E;" />
@@ -107,9 +108,8 @@
         <!-- U+0447: "ч" CYRILLIC SMALL LETTER CHE -->
         <Key
             latin:keyLabel="&#x0447;" />
-        <!-- U+045B: "ћ" CYRILLIC SMALL LETTER TSHE -->
         <Key
-            latin:keyLabel="&#x045B;" />
+            latin:keyLabel="@string/keylabel_for_cyrillic_tshe" />
         <Key
             latin:keyStyle="deleteKeyStyle"
             latin:keyXPos="-9.219%p"
@@ -121,9 +121,8 @@
         <Key
             latin:keyStyle="shiftKeyStyle"
             latin:keyWidth="13.829%p" />
-        <!-- U+0455: "ѕ" CYRILLIC SMALL LETTER DZE -->
         <Key
-            latin:keyLabel="&#x0455;" />
+            latin:keyLabel="@string/keylabel_for_cyrillic_dze" />
         <!-- U+045F: "џ" CYRILLIC SMALL LETTER DZHE -->
         <Key
             latin:keyLabel="&#x045F;" />
@@ -142,6 +141,8 @@
         <!-- U+043C: "м" CYRILLIC SMALL LETTER EM -->
         <Key
             latin:keyLabel="&#x043C;" />
+        <Key
+            latin:keyLabel="@string/keylabel_for_cyrillic_dje" />
         <include
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
diff --git a/java/res/xml-sw768dp/rows_slavic.xml b/java/res/xml-sw768dp/rows_slavic.xml
index 26857ae..3611ef6 100644
--- a/java/res/xml-sw768dp/rows_slavic.xml
+++ b/java/res/xml-sw768dp/rows_slavic.xml
@@ -38,18 +38,18 @@
         <!-- U+0443: "у" CYRILLIC SMALL LETTER U -->
         <Key
             latin:keyLabel="&#x0443;"
-            latin:moreKeys="@string/more_keys_for_slavic_u" />
+            latin:moreKeys="@string/more_keys_for_cyrillic_u" />
         <!-- U+043A: "к" CYRILLIC SMALL LETTER KA -->
         <Key
             latin:keyLabel="&#x043A;" />
         <!-- U+0435: "е" CYRILLIC SMALL LETTER IE -->
         <Key
             latin:keyLabel="&#x0435;"
-            latin:moreKeys="@string/more_keys_for_slavic_ye" />
+            latin:moreKeys="@string/more_keys_for_cyrillic_ye" />
         <!-- U+043D: "н" CYRILLIC SMALL LETTER EN -->
         <Key
             latin:keyLabel="&#x043D;"
-            latin:moreKeys="@string/more_keys_for_slavic_en" />
+            latin:moreKeys="@string/more_keys_for_cyrillic_en" />
         <!-- U+0433: "г" CYRILLIC SMALL LETTER GHE -->
         <Key
             latin:keyLabel="&#x0433;" />
@@ -57,7 +57,7 @@
         <Key
             latin:keyLabel="&#x0448;" />
         <Key
-            latin:keyLabel="@string/keylabel_for_slavic_shcha" />
+            latin:keyLabel="@string/keylabel_for_cyrillic_shcha" />
         <!-- U+0437: "з" CYRILLIC SMALL LETTER ZE -->
         <Key
             latin:keyLabel="&#x0437;" />
@@ -82,8 +82,8 @@
         <Key
             latin:keyLabel="&#x0444;" />
         <Key
-            latin:keyLabel="@string/keylabel_for_slavic_yery"
-            latin:moreKeys="@string/more_keys_for_slavic_yery" />
+            latin:keyLabel="@string/keylabel_for_cyrillic_yery"
+            latin:moreKeys="@string/more_keys_for_cyrillic_yery" />
         <!-- U+0432: "в" CYRILLIC SMALL LETTER VE -->
         <Key
             latin:keyLabel="&#x0432;" />
@@ -99,7 +99,7 @@
         <!-- U+043E: "о" CYRILLIC SMALL LETTER O -->
         <Key
             latin:keyLabel="&#x043E;"
-            latin:moreKeys="@string/more_keys_for_slavic_o" />
+            latin:moreKeys="@string/more_keys_for_cyrillic_o" />
         <!-- U+043B: "л" CYRILLIC SMALL LETTER EL -->
         <Key
             latin:keyLabel="&#x043B;" />
@@ -136,7 +136,7 @@
         <Key
             latin:keyLabel="&#x043C;" />
         <Key
-            latin:keyLabel="@string/keylabel_for_slavic_i" />
+            latin:keyLabel="@string/keylabel_for_cyrillic_i" />
         <!-- U+0442: "т" CYRILLIC SMALL LETTER TE -->
         <Key
             latin:keyLabel="&#x0442;" />
diff --git a/java/res/xml/kbd_greek.xml b/java/res/xml/kbd_greek.xml
new file mode 100644
index 0000000..7056efb
--- /dev/null
+++ b/java/res/xml/kbd_greek.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, 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.
+*/
+-->
+
+<Keyboard
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <include
+        latin:keyboardLayout="@xml/rows_greek" />
+</Keyboard>
diff --git a/java/res/xml/key_styles_enter.xml b/java/res/xml/key_styles_enter.xml
index 61efb89..03bcb86 100644
--- a/java/res/xml/key_styles_enter.xml
+++ b/java/res/xml/key_styles_enter.xml
@@ -49,7 +49,7 @@
             <key-style
                 latin:styleName="navigateMoreKeysStyle"
                 latin:keyLabelFlags="hasPopupHint|preserveCase"
-                latin:moreKeys="!fixedColumnOrder!2,@string/action_previous_as_more_key,@string/action_next_as_more_key" />
+                latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,@string/action_previous_as_more_key,@string/action_next_as_more_key" />
         </case>
         <case
             latin:navigateNext="true"
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index 98dc766..8b1a3ef 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -20,8 +20,9 @@
 <!-- The attributes in this XML file provide configuration information -->
 <!-- for the Input Method Manager. -->
 
-<!-- Keyboard: en_US, en_GB, ar, be, bg, cs, da, de, de(QWERTY), es, es_US, et, fi, fr, fr_CA,
-     fr_CH, hr, hu, it, iw, ka, ky, lt, lv, nb, nl, pl, pt, ro, ru, sk, sl, sr, sv, tr, uk, vi -->
+<!-- Keyboard: en_US, en_GB, ar, be, bg, cs, da, de, de(QWERTY), el, es, es_US, et, fi, fr, fr_CA,
+     fr_CH, hr, hu, it, iw, ka, ky, lt, lv, mk, nb, nl, pl, pt, ro, ru, sk, sl, sr, sv, tr, uk,
+     vi -->
 <!-- TODO: use <lang>_keyboard icon instead of a common keyboard icon. -->
 <!-- If IME doesn't have an applicable subtype, the first subtype will be used as a default
      subtype.-->
@@ -84,6 +85,12 @@
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
+            android:imeSubtypeLocale="el"
+            android:imeSubtypeMode="keyboard"
+            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
+    />
+    <subtype android:icon="@drawable/ic_subtype_keyboard"
+            android:label="@string/subtype_generic"
             android:imeSubtypeLocale="es"
             android:imeSubtypeMode="keyboard"
             android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
@@ -169,6 +176,12 @@
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
+            android:imeSubtypeLocale="mk"
+            android:imeSubtypeMode="keyboard"
+            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
+    />
+    <subtype android:icon="@drawable/ic_subtype_keyboard"
+            android:label="@string/subtype_generic"
             android:imeSubtypeLocale="nb"
             android:imeSubtypeMode="keyboard"
             android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
diff --git a/java/res/xml/rows_greek.xml b/java/res/xml/rows_greek.xml
new file mode 100644
index 0000000..1602c50
--- /dev/null
+++ b/java/res/xml/rows_greek.xml
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, 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"
+>
+    <include
+        latin:keyboardLayout="@xml/key_styles_common" />
+    <Row
+        latin:keyWidth="10%p"
+    >
+        <Key
+            latin:keyLabel=";"
+            latin:keyHintLabel="1"
+            latin:additionalMoreKeys="1" />
+        <!-- TODO: Should find a way to compound Greek dialytika tonos and other Greek letters. -->
+        <!--
+        <switch>
+            <case
+                latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+            >
+                U+0385: "΅" GREEK DIALYTIKA TONOS
+                <Key
+                    latin:keyLabel="&#x0385;"
+                    latin:keyHintLabel="2"
+                    latin:additionalMoreKeys="2" />
+            </case>
+            <default>
+        -->
+                <!-- U+03C2: "ς" GREEK SMALL LETTER FINAL SIGMA -->
+                <Key
+                    latin:keyLabel="&#x03C2;"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="2"
+                    latin:additionalMoreKeys="2" />
+        <!--
+            </default>
+        </switch>
+        -->
+        <!-- U+03B5: "ε" GREEK SMALL LETTER EPSILON
+             U+03AD: "έ" GREEK SMALL LETTER EPSILON WITH TONOS -->
+        <Key
+            latin:keyLabel="&#x03B5;"
+            latin:keyHintLabel="3"
+            latin:additionalMoreKeys="3"
+            latin:moreKeys="&#x03AD;" />
+        <!-- U+03C1: "ρ" GREEK SMALL LETTER RHO -->
+        <Key
+            latin:keyLabel="&#x03C1;"
+            latin:keyHintLabel="4"
+            latin:additionalMoreKeys="4" />
+        <!-- U+03C4: "τ" GREEK SMALL LETTER TAU -->
+        <Key
+            latin:keyLabel="&#x03C4;"
+            latin:keyHintLabel="5"
+            latin:additionalMoreKeys="5" />
+        <!-- U+03C5: "υ" GREEK SMALL LETTER UPSILON
+             U+03CD: "ύ" GREEK SMALL LETTER UPSILON WITH TONOS
+             U+03CB: "ϋ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+             U+03B0: "ΰ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS -->
+        <Key
+            latin:keyLabel="&#x03C5;"
+            latin:keyHintLabel="6"
+            latin:additionalMoreKeys="6"
+            latin:moreKeys="&#x03CD;,&#x03CB;,&#x03B0;" />
+        <!-- U+03B8: "θ" GREEK SMALL LETTER THETA -->
+        <Key
+            latin:keyLabel="&#x03B8;"
+            latin:keyHintLabel="7"
+            latin:additionalMoreKeys="7" />
+        <!-- U+03B9: "ι" GREEK SMALL LETTER IOTA
+             U+03AF: "ί" GREEK SMALL LETTER IOTA WITH TONOS
+             U+03CA: "ϊ" GREEK SMALL LETTER IOTA WITH DIALYTIKA
+             U+0390: "ΐ" GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS -->
+        <Key
+            latin:keyLabel="&#x03B9;"
+            latin:keyHintLabel="8"
+            latin:additionalMoreKeys="8"
+            latin:moreKeys="&#x03AF;,&#x03CA;,&#x0390;" />
+        <!-- U+03BF: "ο" GREEK SMALL LETTER OMICRON
+             U+03CC: "ό" GREEK SMALL LETTER OMICRON WITH TONOS -->
+        <Key
+            latin:keyLabel="&#x03BF;"
+            latin:keyHintLabel="9"
+            latin:additionalMoreKeys="9"
+            latin:moreKeys="&#x03CC;" />
+        <!-- U+03C0: "π" GREEK SMALL LETTER PI -->
+        <Key
+            latin:keyLabel="&#x03C0;"
+            latin:keyHintLabel="0"
+            latin:additionalMoreKeys="0"
+            latin:keyWidth="fillRight" />
+    </Row>
+    <Row
+        latin:keyWidth="10%p"
+    >
+        <!-- U+03B1: "α" GREEK SMALL LETTER ALPHA
+             U+03AC: "ά" GREEK SMALL LETTER ALPHA WITH TONOS -->
+        <Key
+            latin:keyLabel="&#x03B1;"
+            latin:moreKeys="&#x03AC;"
+            latin:keyXPos="5%p" />
+        <!-- U+03C3: "σ" GREEK SMALL LETTER SIGMA -->
+        <Key
+            latin:keyLabel="&#x03C3;" />
+        <!-- U+03B4: "δ" GREEK SMALL LETTER DELTA -->
+        <Key
+            latin:keyLabel="&#x03B4;" />
+        <!-- U+03C6: "φ" GREEK SMALL LETTER PHI -->
+        <Key
+            latin:keyLabel="&#x03C6;" />
+        <!-- U+03B3: "γ" GREEK SMALL LETTER GAMMA -->
+        <Key
+            latin:keyLabel="&#x03B3;" />
+        <!-- U+03B7: "η" GREEK SMALL LETTER ETA
+             U+03AE: "ή" GREEK SMALL LETTER ETA WITH TONOS -->
+        <Key
+            latin:keyLabel="&#x03B7;"
+            latin:moreKeys="&#x03AE;" />
+        <!-- U+03BE: "ξ" GREEK SMALL LETTER XI -->
+        <Key
+            latin:keyLabel="&#x03BE;" />
+        <!-- U+03BA: "κ" GREEK SMALL LETTER KAPPA -->
+        <Key
+            latin:keyLabel="&#x03BA;" />
+        <!-- U+03BB: "λ" GREEK SMALL LETTER LAMDA -->
+        <Key
+            latin:keyLabel="&#x03BB;" />
+        <!-- Here is 5%p space -->
+    </Row>
+    <Row
+        latin:keyWidth="10%p"
+    >
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="15%p"
+            latin:visualInsetsRight="1%p" />
+        <!-- U+03B6: "ζ" GREEK SMALL LETTER ZETA -->
+        <Key
+            latin:keyLabel="&#x03B6;" />
+        <!-- U+03C7: "χ" GREEK SMALL LETTER CHI -->
+        <Key
+            latin:keyLabel="&#x03C7;" />
+        <!-- U+03C8: "ψ" GREEK SMALL LETTER PSI -->
+        <Key
+            latin:keyLabel="&#x03C8;" />
+        <!-- U+03C9: "ω" GREEK SMALL LETTER OMEGA
+             U+03CE: "ώ" GREEK SMALL LETTER OMEGA WITH TONOS -->
+        <Key
+            latin:keyLabel="&#x03C9;"
+            latin:moreKeys="&#x03CE;" />
+        <!-- U+03B2: "β" GREEK SMALL LETTER BETA -->
+        <Key
+            latin:keyLabel="&#x03B2;" />
+        <!-- U+03BD: "ν" GREEK SMALL LETTER NU -->
+        <Key
+            latin:keyLabel="&#x03BD;" />
+        <!-- U+03BC: "μ" GREEK SMALL LETTER MU -->
+        <Key
+            latin:keyLabel="&#x03BC;" />
+        <Key
+            latin:keyStyle="deleteKeyStyle"
+            latin:keyWidth="fillRight"
+            latin:visualInsetsLeft="1%p" />
+    </Row>
+   <include
+        latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/rows_serbian.xml b/java/res/xml/rows_serbian.xml
index cf52fe0..ed33dc7 100644
--- a/java/res/xml/rows_serbian.xml
+++ b/java/res/xml/rows_serbian.xml
@@ -40,7 +40,8 @@
         <Key
             latin:keyLabel="&#x0435;"
             latin:keyHintLabel="3"
-            latin:additionalMoreKeys="3" />
+            latin:additionalMoreKeys="3"
+            latin:moreKeys="@string/more_keys_for_cyrillic_ie" />
         <!-- U+0440: "р" CYRILLIC SMALL LETTER ER -->
         <Key
             latin:keyLabel="&#x0440;"
@@ -51,9 +52,8 @@
             latin:keyLabel="&#x0442;"
             latin:keyHintLabel="5"
             latin:additionalMoreKeys="5" />
-        <!-- U+0437: "з" CYRILLIC SMALL LETTER ZE -->
         <Key
-            latin:keyLabel="&#x0437;"
+            latin:keyLabel="@string/keylabel_for_cyrillic_ze"
             latin:keyHintLabel="6"
             latin:additionalMoreKeys="6" />
         <!-- U+0443: "у" CYRILLIC SMALL LETTER U -->
@@ -65,7 +65,8 @@
         <Key
             latin:keyLabel="&#x0438;"
             latin:keyHintLabel="8"
-            latin:additionalMoreKeys="8" />
+            latin:additionalMoreKeys="8"
+            latin:moreKeys="@string/more_keys_for_cyrillic_i" />
         <!-- U+043E: "о" CYRILLIC SMALL LETTER O -->
         <Key
             latin:keyLabel="&#x043E;"
@@ -114,9 +115,8 @@
         <!-- U+0447: "ч" CYRILLIC SMALL LETTER CHE -->
         <Key
             latin:keyLabel="&#x0447;" />
-        <!-- U+045B: "ћ" CYRILLIC SMALL LETTER TSHE -->
         <Key
-            latin:keyLabel="&#x045B;"
+            latin:keyLabel="@string/keylabel_for_cyrillic_tshe"
             latin:keyWidth="fillRight" />
     </Row>
     <Row
@@ -125,9 +125,8 @@
         <Key
             latin:keyStyle="shiftKeyStyle"
             latin:keyWidth="11.75%p" />
-        <!-- U+0455: "ѕ" CYRILLIC SMALL LETTER DZE -->
         <Key
-            latin:keyLabel="&#x0455;" />
+            latin:keyLabel="@string/keylabel_for_cyrillic_dze" />
         <!-- U+045F: "џ" CYRILLIC SMALL LETTER DZHE -->
         <Key
             latin:keyLabel="&#x045F;" />
@@ -146,9 +145,8 @@
         <!-- U+043C: "м" CYRILLIC SMALL LETTER EM -->
         <Key
             latin:keyLabel="&#x043C;" />
-        <!-- U+0452: "ђ" CYRILLIC SMALL LETTER DJE -->
         <Key
-            latin:keyLabel="&#x0452;" />
+            latin:keyLabel="@string/keylabel_for_cyrillic_dje" />
         <!-- U+0436: "ж" CYRILLIC SMALL LETTER ZHE -->
         <Key
             latin:keyLabel="&#x0436;" />
diff --git a/java/res/xml/rows_slavic.xml b/java/res/xml/rows_slavic.xml
index 4099edd..d75f209 100644
--- a/java/res/xml/rows_slavic.xml
+++ b/java/res/xml/rows_slavic.xml
@@ -41,7 +41,7 @@
             latin:keyLabel="&#x0443;"
             latin:keyHintLabel="3"
             latin:additionalMoreKeys="3"
-            latin:moreKeys="@string/more_keys_for_slavic_u" />
+            latin:moreKeys="@string/more_keys_for_cyrillic_u" />
         <!-- U+043A: "к" CYRILLIC SMALL LETTER KA -->
         <Key
             latin:keyLabel="&#x043A;"
@@ -52,13 +52,13 @@
             latin:keyLabel="&#x0435;"
             latin:keyHintLabel="5"
             latin:additionalMoreKeys="5"
-            latin:moreKeys="@string/more_keys_for_slavic_ye" />
+            latin:moreKeys="@string/more_keys_for_cyrillic_ye" />
         <!-- U+043D: "н" CYRILLIC SMALL LETTER EN -->
         <Key
             latin:keyLabel="&#x043D;"
             latin:keyHintLabel="6"
             latin:additionalMoreKeys="6"
-            latin:moreKeys="@string/more_keys_for_slavic_en" />
+            latin:moreKeys="@string/more_keys_for_cyrillic_en" />
         <!-- U+0433: "г" CYRILLIC SMALL LETTER GHE -->
         <Key
             latin:keyLabel="&#x0433;"
@@ -70,7 +70,7 @@
             latin:keyHintLabel="8"
             latin:additionalMoreKeys="8" />
         <Key
-            latin:keyLabel="@string/keylabel_for_slavic_shcha"
+            latin:keyLabel="@string/keylabel_for_cyrillic_shcha"
             latin:keyHintLabel="9"
             latin:additionalMoreKeys="9" />
         <!-- U+0437: "з" CYRILLIC SMALL LETTER ZE -->
@@ -81,7 +81,7 @@
         <!-- U+0445: "х" CYRILLIC SMALL LETTER HA -->
         <Key
             latin:keyLabel="&#x0445;"
-            latin:moreKeys="@string/more_keys_for_slavic_ha"
+            latin:moreKeys="@string/more_keys_for_cyrillic_ha"
             latin:keyWidth="fillRight" />
     </Row>
     <Row
@@ -91,8 +91,8 @@
         <Key
             latin:keyLabel="&#x0444;" />
         <Key
-            latin:keyLabel="@string/keylabel_for_slavic_yery"
-            latin:moreKeys="@string/more_keys_for_slavic_yery" />
+            latin:keyLabel="@string/keylabel_for_cyrillic_yery"
+            latin:moreKeys="@string/more_keys_for_cyrillic_yery" />
         <!-- U+0432: "в" CYRILLIC SMALL LETTER VE -->
         <Key
             latin:keyLabel="&#x0432;" />
@@ -108,7 +108,7 @@
         <!-- U+043E: "о" CYRILLIC SMALL LETTER O -->
         <Key
             latin:keyLabel="&#x043E;"
-            latin:moreKeys="@string/more_keys_for_slavic_o" />
+            latin:moreKeys="@string/more_keys_for_cyrillic_o" />
         <!-- U+043B: "л" CYRILLIC SMALL LETTER EL -->
         <Key
             latin:keyLabel="&#x043B;" />
@@ -142,14 +142,14 @@
         <Key
             latin:keyLabel="&#x043C;" />
         <Key
-            latin:keyLabel="@string/keylabel_for_slavic_i" />
+            latin:keyLabel="@string/keylabel_for_cyrillic_i" />
         <!-- U+0442: "т" CYRILLIC SMALL LETTER TE -->
         <Key
             latin:keyLabel="&#x0442;" />
         <!-- U+044C: "ь" CYRILLIC SMALL LETTER SOFT SIGN -->
         <Key
             latin:keyLabel="&#x044C;"
-            latin:moreKeys="@string/more_keys_for_slavic_soft_sign" />
+            latin:moreKeys="@string/more_keys_for_cyrillic_soft_sign" />
         <!-- U+0431: "б" CYRILLIC SMALL LETTER BE -->
         <Key
             latin:keyLabel="&#x0431;" />
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
new file mode 100644
index 0000000..dc7c12b
--- /dev/null
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+package com.android.inputmethod.accessibility;
+
+import android.graphics.Rect;
+import android.inputmethodservice.InputMethodService;
+import android.support.v4.view.ViewCompat;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
+import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat;
+import android.support.v4.view.accessibility.AccessibilityRecordCompat;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.View;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.inputmethod.EditorInfo;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardView;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Exposes a virtual view sub-tree for {@link KeyboardView} and generates
+ * {@link AccessibilityEvent}s for individual {@link Key}s.
+ * <p>
+ * A virtual sub-tree is composed of imaginary {@link View}s that are reported
+ * as a part of the view hierarchy for accessibility purposes. This enables
+ * custom views that draw complex content to report them selves as a tree of
+ * virtual views, thus conveying their logical structure.
+ * </p>
+ */
+public class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat {
+    private static final String TAG = AccessibilityEntityProvider.class.getSimpleName();
+
+    private final KeyboardView mKeyboardView;
+    private final InputMethodService mInputMethodService;
+    private final KeyCodeDescriptionMapper mKeyCodeDescriptionMapper;
+    private final AccessibilityUtils mAccessibilityUtils;
+
+    /** A map of integer IDs to {@link Key}s. */
+    private final SparseArray<Key> mVirtualViewIdToKey = new SparseArray<Key>();
+
+    /** Temporary rect used to calculate in-screen bounds. */
+    private final Rect mTempBoundsInScreen = new Rect();
+
+    /** The parent view's cached on-screen location. */
+    private final int[] mParentLocation = new int[2];
+
+    public AccessibilityEntityProvider(KeyboardView keyboardView, InputMethodService inputMethod) {
+        mKeyboardView = keyboardView;
+        mInputMethodService = inputMethod;
+
+        mKeyCodeDescriptionMapper = KeyCodeDescriptionMapper.getInstance();
+        mAccessibilityUtils = AccessibilityUtils.getInstance();
+
+        assignVirtualViewIds();
+        updateParentLocation();
+
+        // Ensure that the on-screen bounds are cleared when the layout changes.
+        mKeyboardView.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener);
+    }
+
+    /**
+     * Creates and populates an {@link AccessibilityEvent} for the specified key
+     * and event type.
+     *
+     * @param key A key on the host keyboard view.
+     * @param eventType The event type to create.
+     * @return A populated {@link AccessibilityEvent} for the key.
+     * @see AccessibilityEvent
+     */
+    public AccessibilityEvent createAccessibilityEvent(Key key, int eventType) {
+        final int virtualViewId = generateVirtualViewIdForKey(key);
+        final String keyDescription = getKeyDescription(key);
+
+        final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
+        event.setPackageName(mKeyboardView.getContext().getPackageName());
+        event.setClassName(key.getClass().getName());
+        event.getText().add(keyDescription);
+
+        final AccessibilityRecordCompat record = new AccessibilityRecordCompat(event);
+        record.setSource(mKeyboardView, virtualViewId);
+
+        return event;
+    }
+
+    /**
+     * Returns an {@link AccessibilityNodeInfoCompat} representing a virtual
+     * view, i.e. a descendant of the host View, with the given <code>virtualViewId</code> or
+     * the host View itself if <code>virtualViewId</code> equals to {@link View#NO_ID}.
+     * <p>
+     * A virtual descendant is an imaginary View that is reported as a part of
+     * the view hierarchy for accessibility purposes. This enables custom views
+     * that draw complex content to report them selves as a tree of virtual
+     * views, thus conveying their logical structure.
+     * </p>
+     * <p>
+     * The implementer is responsible for obtaining an accessibility node info
+     * from the pool of reusable instances and setting the desired properties of
+     * the node info before returning it.
+     * </p>
+     *
+     * @param virtualViewId A client defined virtual view id.
+     * @return A populated {@link AccessibilityNodeInfoCompat} for a virtual
+     *         descendant or the host View.
+     * @see AccessibilityNodeInfoCompat
+     */
+    @Override
+    public AccessibilityNodeInfoCompat createAccessibilityNodeInfo(int virtualViewId) {
+        AccessibilityNodeInfoCompat info = null;
+
+        if (virtualViewId == View.NO_ID) {
+            // We are requested to create an AccessibilityNodeInfo describing
+            // this View, i.e. the root of the virtual sub-tree.
+            info = AccessibilityNodeInfoCompat.obtain(mKeyboardView);
+            ViewCompat.onInitializeAccessibilityNodeInfo(mKeyboardView, info);
+
+            // Add the virtual children of the root View.
+            // TODO(alanv): Need to assign a unique ID to each key.
+            final Keyboard keyboard = mKeyboardView.getKeyboard();
+            final Set<Key> keys = keyboard.mKeys;
+            for (Key key : keys) {
+                final int childVirtualViewId = generateVirtualViewIdForKey(key);
+                info.addChild(mKeyboardView, childVirtualViewId);
+            }
+        } else {
+            // Find the view that corresponds to the given id.
+            final Key key = mVirtualViewIdToKey.get(virtualViewId);
+            if (key == null) {
+                Log.e(TAG, "Invalid virtual view ID: " + virtualViewId);
+                return null;
+            }
+
+            final String keyDescription = getKeyDescription(key);
+            final Rect boundsInParent = key.mHitBox;
+
+            // Calculate the key's in-screen bounds.
+            mTempBoundsInScreen.set(boundsInParent);
+            mTempBoundsInScreen.offset(mParentLocation[0], mParentLocation[1]);
+
+            final Rect boundsInScreen = mTempBoundsInScreen;
+
+            // Obtain and initialize an AccessibilityNodeInfo with
+            // information about the virtual view.
+            info = AccessibilityNodeInfoCompat.obtain();
+            info.addAction(AccessibilityNodeInfoCompat.ACTION_SELECT);
+            info.addAction(AccessibilityNodeInfoCompat.ACTION_CLEAR_SELECTION);
+            info.setPackageName(mKeyboardView.getContext().getPackageName());
+            info.setClassName(key.getClass().getName());
+            info.setBoundsInParent(boundsInParent);
+            info.setBoundsInScreen(boundsInScreen);
+            info.setParent(mKeyboardView);
+            info.setSource(mKeyboardView, virtualViewId);
+            info.setBoundsInScreen(boundsInScreen);
+            info.setText(keyDescription);
+        }
+
+        return info;
+    }
+
+    /**
+     * Performs an accessibility action on a virtual view, i.e. a descendant of
+     * the host View, with the given <code>virtualViewId</code> or the host View itself if
+     * <code>virtualViewId</code> equals to {@link View#NO_ID}.
+     *
+     * @param action The action to perform.
+     * @param virtualViewId A client defined virtual view id.
+     * @return True if the action was performed.
+     * @see #createAccessibilityNodeInfo(int)
+     * @see AccessibilityNodeInfoCompat
+     */
+    @Override
+    public boolean performAccessibilityAction(int action, int virtualViewId) {
+        if (virtualViewId == View.NO_ID) {
+            // Perform the action on the host View.
+            switch (action) {
+            case AccessibilityNodeInfoCompat.ACTION_SELECT:
+                if (!mKeyboardView.isSelected()) {
+                    mKeyboardView.setSelected(true);
+                    return mKeyboardView.isSelected();
+                }
+                break;
+            case AccessibilityNodeInfoCompat.ACTION_CLEAR_SELECTION:
+                if (mKeyboardView.isSelected()) {
+                    mKeyboardView.setSelected(false);
+                    return !mKeyboardView.isSelected();
+                }
+                break;
+            }
+        } else {
+            // Find the view that corresponds to the given id.
+            final Key child = mVirtualViewIdToKey.get(virtualViewId);
+            if (child == null)
+                return false;
+
+            // Perform the action on a virtual view.
+            switch (action) {
+            case AccessibilityNodeInfoCompat.ACTION_SELECT:
+                // TODO: Provide some focus indicator.
+                return true;
+            case AccessibilityNodeInfoCompat.ACTION_CLEAR_SELECTION:
+                // TODO: Provide some clear focus indicator.
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Finds {@link AccessibilityNodeInfoCompat}s by text. The match is case
+     * insensitive containment. The search is relative to the virtual view, i.e.
+     * a descendant of the host View, with the given <code>virtualViewId</code> or the host
+     * View itself <code>virtualViewId</code> equals to {@link View#NO_ID}.
+     *
+     * @param virtualViewId A client defined virtual view id which defined the
+     *            root of the tree in which to perform the search.
+     * @param text The searched text.
+     * @return A list of node info.
+     * @see #createAccessibilityNodeInfo(int)
+     * @see AccessibilityNodeInfoCompat
+     */
+    @Override
+    public List<AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByText(
+            String text, int virtualViewId) {
+        final String searchedLowerCase = text.toLowerCase();
+        final Keyboard keyboard = mKeyboardView.getKeyboard();
+
+        List<AccessibilityNodeInfoCompat> results = null;
+
+        if (virtualViewId == View.NO_ID) {
+            for (Key key : keyboard.mKeys) {
+                results = findByTextAndPopulate(searchedLowerCase, key, results);
+            }
+        } else {
+            final Key key = mVirtualViewIdToKey.get(virtualViewId);
+
+            results = findByTextAndPopulate(searchedLowerCase, key, results);
+        }
+
+        if (results == null) {
+            return Collections.emptyList();
+        }
+
+        return results;
+    }
+
+    /**
+     * Helper method for {@link #findAccessibilityNodeInfosByText(String, int)}.
+     * Takes a current set of results and matches a specified key against a
+     * lower-case search string. Returns an updated list of results.
+     *
+     * @param searchedLowerCase The lower-case search string.
+     * @param key The key to compare against.
+     * @param results The current list of results, or {@code null} if no results
+     *            found.
+     * @return An updated list of results, or {@code null} if no results found.
+     */
+    private List<AccessibilityNodeInfoCompat> findByTextAndPopulate(String searchedLowerCase,
+            Key key, List<AccessibilityNodeInfoCompat> results) {
+        if (!keyContainsText(key, searchedLowerCase)) {
+            return results;
+        }
+
+        final int childVirtualViewId = generateVirtualViewIdForKey(key);
+        final AccessibilityNodeInfoCompat nodeInfo = createAccessibilityNodeInfo(
+                childVirtualViewId);
+
+        if (results == null) {
+            results = new LinkedList<AccessibilityNodeInfoCompat>();
+        }
+
+        results.add(nodeInfo);
+
+        return results;
+    }
+
+    /**
+     * Returns whether a key's current description contains the lower-case
+     * search text.
+     *
+     * @param key The key to compare against.
+     * @param textLowerCase The lower-case search string.
+     * @return {@code true} if the key contains the search text.
+     */
+    private boolean keyContainsText(Key key, String textLowerCase) {
+        if (key == null) {
+            return false;
+        }
+
+        final String description = getKeyDescription(key);
+
+        if (description == null) {
+            return false;
+        }
+
+        return description.toLowerCase().contains(textLowerCase);
+    }
+
+    /**
+     * Returns the context-specific description for a {@link Key}.
+     *
+     * @param key The key to describe.
+     * @return The context-specific description of the key.
+     */
+    private String getKeyDescription(Key key) {
+        final EditorInfo editorInfo = mInputMethodService.getCurrentInputEditorInfo();
+        final boolean shouldObscure = mAccessibilityUtils.shouldObscureInput(editorInfo);
+        final String keyDescription = mKeyCodeDescriptionMapper.getDescriptionForKey(
+                mKeyboardView.getContext(), mKeyboardView.getKeyboard(), key, shouldObscure);
+
+        return keyDescription;
+    }
+
+    /**
+     * Assigns virtual view IDs to keyboard keys and populates the related maps.
+     */
+    private void assignVirtualViewIds() {
+        final Keyboard keyboard = mKeyboardView.getKeyboard();
+        if (keyboard == null) {
+            return;
+        }
+
+        mVirtualViewIdToKey.clear();
+
+        final Set<Key> keySet = keyboard.mKeys;
+        for (Key key : keySet) {
+            final int virtualViewId = generateVirtualViewIdForKey(key);
+            mVirtualViewIdToKey.put(virtualViewId, key);
+        }
+    }
+
+    /**
+     * Updates the parent's on-screen location.
+     */
+    private void updateParentLocation() {
+        mKeyboardView.getLocationOnScreen(mParentLocation);
+    }
+
+    /**
+     * Generates a virtual view identifier for the specified key.
+     *
+     * @param key The key to identify.
+     * @return A virtual view identifier.
+     */
+    private static int generateVirtualViewIdForKey(Key key) {
+        // The key code is unique within an instance of a Keyboard.
+        return key.mCode;
+    }
+
+    private final OnGlobalLayoutListener mGlobalLayoutListener = new OnGlobalLayoutListener() {
+        @Override
+        public void onGlobalLayout() {
+            assignVirtualViewIds();
+            updateParentLocation();
+        }
+    };
+}
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
index 9caed00..41da2aa 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
@@ -21,13 +21,14 @@
 import android.media.AudioManager;
 import android.os.SystemClock;
 import android.provider.Settings;
+import android.support.v4.view.MotionEventCompat;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.inputmethod.EditorInfo;
 
-import com.android.inputmethod.compat.AccessibilityManagerCompatWrapper;
+import com.android.inputmethod.compat.AccessibilityManagerCompatUtils;
 import com.android.inputmethod.compat.AudioManagerCompatWrapper;
 import com.android.inputmethod.compat.InputTypeCompatUtils;
 import com.android.inputmethod.compat.MotionEventCompatUtils;
@@ -44,7 +45,6 @@
 
     private Context mContext;
     private AccessibilityManager mAccessibilityManager;
-    private AccessibilityManagerCompatWrapper mCompatManager;
     private AudioManagerCompatWrapper mAudioManager;
 
     /*
@@ -77,7 +77,6 @@
         mContext = context;
         mAccessibilityManager = (AccessibilityManager) context
                 .getSystemService(Context.ACCESSIBILITY_SERVICE);
-        mCompatManager = new AccessibilityManagerCompatWrapper(mAccessibilityManager);
 
         final AudioManager audioManager = (AudioManager) context
                 .getSystemService(Context.AUDIO_SERVICE);
@@ -94,7 +93,7 @@
     public boolean isTouchExplorationEnabled() {
         return ENABLE_ACCESSIBILITY
                 && mAccessibilityManager.isEnabled()
-                && mCompatManager.isTouchExplorationEnabled();
+                && AccessibilityManagerCompatUtils.isTouchExplorationEnabled(mAccessibilityManager);
     }
 
     /**
@@ -110,13 +109,13 @@
 
         return action == MotionEventCompatUtils.ACTION_HOVER_ENTER
                 || action == MotionEventCompatUtils.ACTION_HOVER_EXIT
-                || action == MotionEventCompatUtils.ACTION_HOVER_MOVE;
+                || action == MotionEventCompat.ACTION_HOVER_MOVE;
     }
 
     /**
      * Returns whether the device should obscure typed password characters.
      * Typically this means speaking "dot" in place of non-control characters.
-     * 
+     *
      * @return {@code true} if the device should obscure password characters.
      */
     public boolean shouldObscureInput(EditorInfo editorInfo) {
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
index 2294a18..2401d93 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
@@ -20,13 +20,16 @@
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.inputmethodservice.InputMethodService;
-import android.util.Log;
+import android.support.v4.view.AccessibilityDelegateCompat;
+import android.support.v4.view.MotionEventCompat;
+import android.support.v4.view.ViewCompat;
+import android.support.v4.view.accessibility.AccessibilityEventCompat;
 import android.view.MotionEvent;
+import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.inputmethod.EditorInfo;
 
-import com.android.inputmethod.compat.AccessibilityEventCompatUtils;
 import com.android.inputmethod.compat.MotionEventCompatUtils;
+import com.android.inputmethod.compat.ViewParentCompatUtils;
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.keyboard.KeyboardId;
@@ -34,14 +37,14 @@
 import com.android.inputmethod.keyboard.PointerTracker;
 import com.android.inputmethod.latin.R;
 
-public class AccessibleKeyboardViewProxy {
-    private static final String TAG = AccessibleKeyboardViewProxy.class.getSimpleName();
+public class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat {
     private static final AccessibleKeyboardViewProxy sInstance = new AccessibleKeyboardViewProxy();
 
     private InputMethodService mInputMethod;
     private FlickGestureDetector mGestureDetector;
     private LatinKeyboardView mView;
     private AccessibleKeyboardActionListener mListener;
+    private AccessibilityEntityProvider mAccessibilityNodeProvider;
 
     private Key mLastHoverKey = null;
 
@@ -54,10 +57,6 @@
         return sInstance;
     }
 
-    public static void setView(LatinKeyboardView view) {
-        sInstance.mView = view;
-    }
-
     private AccessibleKeyboardViewProxy() {
         // Not publicly instantiable.
     }
@@ -73,34 +72,39 @@
         mGestureDetector = new KeyboardFlickGestureDetector(inputMethod);
     }
 
-    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
-        if (mView == null) {
-            Log.e(TAG, "No keyboard view set!");
-            return false;
+    /**
+     * Sets the view wrapped by this proxy.
+     *
+     * @param view The view to wrap.
+     */
+    public void setView(LatinKeyboardView view) {
+        if (view == null) {
+            // Ignore null views.
+            return;
         }
 
-        switch (event.getEventType()) {
-        case AccessibilityEventCompatUtils.TYPE_VIEW_HOVER_ENTER:
-            final Key key = mLastHoverKey;
+        mView = view;
 
-            if (key == null)
-                break;
+        // Ensure that the view has an accessibility delegate.
+        ViewCompat.setAccessibilityDelegate(view, this);
+    }
 
-            final EditorInfo info = mInputMethod.getCurrentInputEditorInfo();
-            final boolean shouldObscure = AccessibilityUtils.getInstance().shouldObscureInput(info);
-            final CharSequence description = KeyCodeDescriptionMapper.getInstance()
-                    .getDescriptionForKey(mView.getContext(), mView.getKeyboard(), key,
-                            shouldObscure);
-
-            if (description == null)
-                return false;
-
-            event.getText().add(description);
-
-            break;
+    /**
+     * Proxy method for View.getAccessibilityNodeProvider(). This method is
+     * called in SDK version 15 and higher to obtain the virtual node hierarchy
+     * provider.
+     *
+     * @return The accessibility node provider for the current keyboard.
+     */
+    @Override
+    public AccessibilityEntityProvider getAccessibilityNodeProvider(View host) {
+        // Instantiate the provide only when requested. Since the system
+        // will call this method multiple times it is a good practice to
+        // cache the provider instance.
+        if (mAccessibilityNodeProvider == null) {
+            mAccessibilityNodeProvider = new AccessibilityEntityProvider(mView, mInputMethod);
         }
-
-        return true;
+        return mAccessibilityNodeProvider;
     }
 
     /**
@@ -123,46 +127,94 @@
      * @param event The touch exploration hover event.
      * @return {@code true} if the event was handled
      */
-    /*package*/ boolean onHoverEventInternal(MotionEvent event, PointerTracker tracker) {
+    /* package */boolean onHoverEventInternal(MotionEvent event, PointerTracker tracker) {
         final int x = (int) event.getX();
         final int y = (int) event.getY();
+        final Key key = tracker.getKeyOn(x, y);
+        final Key previousKey = mLastHoverKey;
+
+        mLastHoverKey = key;
 
         switch (event.getAction()) {
         case MotionEventCompatUtils.ACTION_HOVER_ENTER:
-        case MotionEventCompatUtils.ACTION_HOVER_MOVE:
-            final Key key = tracker.getKeyOn(x, y);
-
-            if (key != mLastHoverKey) {
-                fireKeyHoverEvent(mLastHoverKey, false);
-                mLastHoverKey = key;
-                fireKeyHoverEvent(mLastHoverKey, true);
+        case MotionEventCompatUtils.ACTION_HOVER_EXIT:
+            return onHoverKey(key, event);
+        case MotionEventCompat.ACTION_HOVER_MOVE:
+            if (key != previousKey) {
+                return onTransitionKey(key, previousKey, event);
+            } else {
+                return onHoverKey(key, event);
             }
-
-            return true;
         }
 
         return false;
     }
 
-    private void fireKeyHoverEvent(Key key, boolean entering) {
-        if (mListener == null) {
-            Log.e(TAG, "No accessible keyboard action listener set!");
-            return;
+    /**
+     * Simulates a transition between two {@link Key}s by sending a HOVER_EXIT
+     * on the previous key, a HOVER_ENTER on the current key, and a HOVER_MOVE
+     * on the current key.
+     *
+     * @param currentKey The currently hovered key.
+     * @param previousKey The previously hovered key.
+     * @param event The event that triggered the transition.
+     * @return {@code true} if the event was handled.
+     */
+    private boolean onTransitionKey(Key currentKey, Key previousKey, MotionEvent event) {
+        final int savedAction = event.getAction();
+
+        event.setAction(MotionEventCompatUtils.ACTION_HOVER_EXIT);
+        onHoverKey(previousKey, event);
+
+        event.setAction(MotionEventCompatUtils.ACTION_HOVER_ENTER);
+        onHoverKey(currentKey, event);
+
+        event.setAction(MotionEventCompat.ACTION_HOVER_MOVE);
+        final boolean handled = onHoverKey(currentKey, event);
+
+        event.setAction(savedAction);
+
+        return handled;
+    }
+
+    /**
+     * Handles a hover event on a key. If {@link Key} extended View, this would
+     * be analogous to calling View.onHoverEvent(MotionEvent).
+     *
+     * @param key The currently hovered key.
+     * @param event The hover event.
+     * @return {@code true} if the event was handled.
+     */
+    private boolean onHoverKey(Key key, MotionEvent event) {
+        // Null keys can't receive events.
+        if (key == null) {
+            return false;
         }
 
-        if (mView == null) {
-            Log.e(TAG, "No keyboard view set!");
-            return;
+        switch (event.getAction()) {
+        case MotionEventCompatUtils.ACTION_HOVER_ENTER:
+            sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_VIEW_HOVER_ENTER);
+            break;
+        case MotionEventCompatUtils.ACTION_HOVER_EXIT:
+            sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_VIEW_HOVER_EXIT);
+            break;
         }
 
-        if (key == null)
-            return;
+        return true;
+    }
 
-        if (entering) {
-            mView.sendAccessibilityEvent(AccessibilityEventCompatUtils.TYPE_VIEW_HOVER_ENTER);
-        } else {
-            mView.sendAccessibilityEvent(AccessibilityEventCompatUtils.TYPE_VIEW_HOVER_EXIT);
-        }
+    /**
+     * Populates and sends an {@link AccessibilityEvent} for the specified key.
+     *
+     * @param key The key to send an event for.
+     * @param eventType The type of event to send.
+     */
+    private void sendAccessibilityEventForKey(Key key, int eventType) {
+        final AccessibilityEntityProvider nodeProvider = getAccessibilityNodeProvider(null);
+        final AccessibilityEvent event = nodeProvider.createAccessibilityEvent(key, eventType);
+
+        // Propagates the event up the view hierarchy.
+        ViewParentCompatUtils.requestSendAccessibilityEvent(mView.getParent(), mView, event);
     }
 
     private class KeyboardFlickGestureDetector extends FlickGestureDetector {
diff --git a/java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java b/java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java
index db12f76..eaa4ddf 100644
--- a/java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java
+++ b/java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.os.Message;
+import android.support.v4.view.MotionEventCompat;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 
@@ -32,7 +33,7 @@
  * properties:
  * <ul>
  *   <li>Begins with a {@link MotionEventCompatUtils#ACTION_HOVER_ENTER} event
- *   <li>Contains any number of {@link MotionEventCompatUtils#ACTION_HOVER_MOVE}
+ *   <li>Contains any number of {@link MotionEventCompat#ACTION_HOVER_MOVE}
  *       events
  *   <li>Ends with a {@link MotionEventCompatUtils#ACTION_HOVER_EXIT} event
  *   <li>Maximum duration of 250 milliseconds
@@ -128,7 +129,7 @@
         final float distanceSquare = calculateDistanceSquare(mCachedHoverEnter, event);
 
         switch (event.getAction()) {
-        case MotionEventCompatUtils.ACTION_HOVER_MOVE:
+        case MotionEventCompat.ACTION_HOVER_MOVE:
             // Consume all valid move events before timeout.
             return true;
         case MotionEventCompatUtils.ACTION_HOVER_EXIT:
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index f0dba4a..3d861c2 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.text.TextUtils;
+import android.util.Log;
 
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.Keyboard;
@@ -27,6 +28,8 @@
 import java.util.HashMap;
 
 public class KeyCodeDescriptionMapper {
+    private static final String TAG = KeyCodeDescriptionMapper.class.getSimpleName();
+
     // The resource ID of the string spoken for obscured keys
     private static final int OBSCURED_KEY_RES_ID = R.string.spoken_description_dot;
 
@@ -87,12 +90,12 @@
      * @return a character sequence describing the action performed by pressing
      *         the key
      */
-    public CharSequence getDescriptionForKey(Context context, Keyboard keyboard, Key key,
+    public String getDescriptionForKey(Context context, Keyboard keyboard, Key key,
             boolean shouldObscure) {
         final int code = key.mCode;
 
         if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
-            final CharSequence description = getDescriptionForSwitchAlphaSymbol(context, keyboard);
+            final String description = getDescriptionForSwitchAlphaSymbol(context, keyboard);
             if (description != null)
                 return description;
         }
@@ -128,7 +131,7 @@
      * @return a character sequence describing the action performed by pressing
      *         the key
      */
-    private CharSequence getDescriptionForSwitchAlphaSymbol(Context context, Keyboard keyboard) {
+    private String getDescriptionForSwitchAlphaSymbol(Context context, Keyboard keyboard) {
         final KeyboardId keyboardId = keyboard.mId;
         final int elementId = keyboardId.mElementId;
         final int resId;
@@ -152,10 +155,7 @@
             resId = R.string.spoken_description_to_numeric;
             break;
         default:
-            resId = -1;
-        }
-
-        if (resId < 0) {
+            Log.e(TAG, "Missing description for keyboard element ID:" + elementId);
             return null;
         }
 
@@ -169,7 +169,7 @@
      * @param keyboard The keyboard on which the key resides.
      * @return A context-sensitive description of the "Shift" key.
      */
-    private CharSequence getDescriptionForShiftKey(Context context, Keyboard keyboard) {
+    private String getDescriptionForShiftKey(Context context, Keyboard keyboard) {
         final KeyboardId keyboardId = keyboard.mId;
         final int elementId = keyboardId.mElementId;
         final int resId;
@@ -212,7 +212,7 @@
      * @return a character sequence describing the action performed by pressing
      *         the key
      */
-    private CharSequence getDescriptionForKeyCode(Context context, Keyboard keyboard, Key key,
+    private String getDescriptionForKeyCode(Context context, Keyboard keyboard, Key key,
             boolean shouldObscure) {
         final int code = key.mCode;
 
diff --git a/java/src/com/android/inputmethod/compat/AccessibilityEventCompatUtils.java b/java/src/com/android/inputmethod/compat/AccessibilityEventCompatUtils.java
deleted file mode 100644
index 2fa9d87..0000000
--- a/java/src/com/android/inputmethod/compat/AccessibilityEventCompatUtils.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-package com.android.inputmethod.compat;
-
-public class AccessibilityEventCompatUtils {
-    public static final int TYPE_VIEW_HOVER_ENTER = 0x80;
-    public static final int TYPE_VIEW_HOVER_EXIT = 0x100;
-}
diff --git a/java/src/com/android/inputmethod/compat/AccessibilityManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/AccessibilityManagerCompatUtils.java
similarity index 74%
rename from java/src/com/android/inputmethod/compat/AccessibilityManagerCompatWrapper.java
rename to java/src/com/android/inputmethod/compat/AccessibilityManagerCompatUtils.java
index a30af0f..41b6a07 100644
--- a/java/src/com/android/inputmethod/compat/AccessibilityManagerCompatWrapper.java
+++ b/java/src/com/android/inputmethod/compat/AccessibilityManagerCompatUtils.java
@@ -20,17 +20,15 @@
 
 import java.lang.reflect.Method;
 
-public class AccessibilityManagerCompatWrapper {
+public class AccessibilityManagerCompatUtils {
     private static final Method METHOD_isTouchExplorationEnabled = CompatUtils.getMethod(
             AccessibilityManager.class, "isTouchExplorationEnabled");
 
-    private final AccessibilityManager mManager;
-
-    public AccessibilityManagerCompatWrapper(AccessibilityManager manager) {
-        mManager = manager;
+    private AccessibilityManagerCompatUtils() {
+        // This class is non-instantiable.
     }
 
-    public boolean isTouchExplorationEnabled() {
-        return (Boolean) CompatUtils.invoke(mManager, false, METHOD_isTouchExplorationEnabled);
+    public static boolean isTouchExplorationEnabled(AccessibilityManager receiver) {
+        return (Boolean) CompatUtils.invoke(receiver, false, METHOD_isTouchExplorationEnabled);
     }
 }
diff --git a/java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java b/java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java
index 8518a4a..eca922e 100644
--- a/java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java
@@ -17,7 +17,7 @@
 package com.android.inputmethod.compat;
 
 public class MotionEventCompatUtils {
-    public static final int ACTION_HOVER_MOVE = 0x7;
+    // TODO(alanv): Remove after these are added to MotionEventCompat.
     public static final int ACTION_HOVER_ENTER = 0x9;
     public static final int ACTION_HOVER_EXIT = 0xA;
 }
diff --git a/java/src/com/android/inputmethod/compat/ViewParentCompatUtils.java b/java/src/com/android/inputmethod/compat/ViewParentCompatUtils.java
new file mode 100644
index 0000000..d19bc3a
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/ViewParentCompatUtils.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+package com.android.inputmethod.compat;
+
+import android.view.View;
+import android.view.ViewParent;
+import android.view.accessibility.AccessibilityEvent;
+
+import java.lang.reflect.Method;
+
+public class ViewParentCompatUtils {
+    private static final Method METHOD_requestSendAccessibilityEvent = CompatUtils.getMethod(
+            ViewParent.class, "requestSendAccessibilityEvent", View.class,
+            AccessibilityEvent.class);
+
+    /**
+     * Called by a child to request from its parent to send an {@link AccessibilityEvent}.
+     * The child has already populated a record for itself in the event and is delegating
+     * to its parent to send the event. The parent can optionally add a record for itself.
+     * <p>
+     * Note: An accessibility event is fired by an individual view which populates the
+     *       event with a record for its state and requests from its parent to perform
+     *       the sending. The parent can optionally add a record for itself before
+     *       dispatching the request to its parent. A parent can also choose not to
+     *       respect the request for sending the event. The accessibility event is sent
+     *       by the topmost view in the view tree.</p>
+     *
+     * @param child The child which requests sending the event.
+     * @param event The event to be sent.
+     * @return True if the event was sent.
+     */
+    public static boolean requestSendAccessibilityEvent(
+            ViewParent receiver, View child, AccessibilityEvent event) {
+        return (Boolean) CompatUtils.invoke(
+                receiver, false, METHOD_requestSendAccessibilityEvent, child, event);
+    }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index f1611d9..a719b4a 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -108,9 +108,11 @@
     private static final int MORE_KEYS_COLUMN_MASK = 0x000000ff;
     private static final int MORE_KEYS_FLAGS_FIXED_COLUMN_ORDER = 0x80000000;
     private static final int MORE_KEYS_FLAGS_HAS_LABELS = 0x40000000;
+    private static final int MORE_KEYS_FLAGS_NEEDS_DIVIDERS = 0x40000000;
     private static final String MORE_KEYS_AUTO_COLUMN_ORDER = "!autoColumnOrder!";
     private static final String MORE_KEYS_FIXED_COLUMN_ORDER = "!fixedColumnOrder!";
     private static final String MORE_KEYS_HAS_LABELS = "!hasLabels!";
+    private static final String MORE_KEYS_NEEDS_DIVIDERS = "!needsDividers!";
 
     /** Background type that represents different key background visual than normal one. */
     public final int mBackgroundType;
@@ -253,6 +255,9 @@
         if (KeySpecParser.getBooleanValue(moreKeys, MORE_KEYS_HAS_LABELS)) {
             moreKeysColumn |= MORE_KEYS_FLAGS_HAS_LABELS;
         }
+        if (KeySpecParser.getBooleanValue(moreKeys, MORE_KEYS_NEEDS_DIVIDERS)) {
+            moreKeysColumn |= MORE_KEYS_FLAGS_NEEDS_DIVIDERS;
+        }
         mMoreKeysColumnAndFlags = moreKeysColumn;
 
         final String[] additionalMoreKeys = style.getStringArray(
@@ -539,6 +544,10 @@
         return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_HAS_LABELS) != 0;
     }
 
+    public boolean needsDividersInMoreKeys() {
+        return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_NEEDS_DIVIDERS) != 0;
+    }
+
     public Drawable getIcon(KeyboardIconsSet iconSet) {
         return iconSet.getIconDrawable(mIconId);
     }
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 622e583..e1c6f26 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -379,7 +379,7 @@
 
         // This always needs to be set since the accessibility state can
         // potentially change without the input view being re-created.
-        AccessibleKeyboardViewProxy.setView(mKeyboardView);
+        AccessibleKeyboardViewProxy.getInstance().setView(mKeyboardView);
 
         return mCurrentInputView;
     }
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 89dad7b..99bd080 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -34,7 +34,6 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityEvent;
 import android.widget.PopupWindow;
 
 import com.android.inputmethod.accessibility.AccessibilityUtils;
@@ -481,8 +480,11 @@
      */
     protected boolean onLongPress(Key parentKey, PointerTracker tracker) {
         final int primaryCode = parentKey.mCode;
-        if (parentKey.mAltCode != Keyboard.CODE_UNSPECIFIED) {
-            // Long press on a key that has altCode defined.
+        if (parentKey.mMoreKeys == null && !parentKey.altCodeWhileTyping()
+                && parentKey.mAltCode != Keyboard.CODE_UNSPECIFIED) {
+            // Long press on a key that has no more keys and not altCodeWhileTyping but altCode
+            // defined, such as "0 +" key on phone layout and "/ :" key on datetime
+            // layout.
             tracker.onLongPressed();
             invokeCodeInput(parentKey.mAltCode);
             invokeReleaseKey(primaryCode);
@@ -731,16 +733,6 @@
         VoiceProxy.getInstance().onAttachedToWindow();
     }
 
-    @Override
-    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
-        if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) {
-            return AccessibleKeyboardViewProxy.getInstance().dispatchPopulateAccessibilityEvent(
-                    event) || super.dispatchPopulateAccessibilityEvent(event);
-        }
-
-        return super.dispatchPopulateAccessibilityEvent(event);
-    }
-
     /**
      * Receives hover events from the input framework. This method overrides
      * View.dispatchHoverEvent(MotionEvent) on SDK version ICS or higher. On
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
index abbdfdd..9f735cf 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
@@ -17,8 +17,10 @@
 package com.android.inputmethod.keyboard;
 
 import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
 
 import com.android.inputmethod.keyboard.internal.KeySpecParser;
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.Utils;
 
@@ -36,8 +38,10 @@
 
     public static class Builder extends Keyboard.Builder<Builder.MoreKeysKeyboardParams> {
         private final Key mParentKey;
+        private final Drawable mDivider;
 
         private static final float LABEL_PADDING_RATIO = 0.2f;
+        private static final float DIVIDER_RATIO = 0.2f;
 
         public static class MoreKeysKeyboardParams extends Keyboard.Params {
             public boolean mIsFixedOrder;
@@ -47,6 +51,8 @@
             public int mTopKeys;
             public int mLeftKeys;
             public int mRightKeys; // includes default key.
+            public int mDividerWidth;
+            public int mColumnWidth;
 
             public MoreKeysKeyboardParams() {
                 super();
@@ -62,9 +68,11 @@
              * @param coordXInParent coordinate x of the key preview in parent keyboard.
              * @param parentKeyboardWidth parent keyboard width in pixel.
              * @param isFixedColumnOrder if true, more keys should be laid out in fixed order.
+             * @param dividerWidth width of divider, zero for no dividers.
              */
             public void setParameters(int numKeys, int maxColumns, int keyWidth, int rowHeight,
-                    int coordXInParent, int parentKeyboardWidth, boolean isFixedColumnOrder) {
+                    int coordXInParent, int parentKeyboardWidth, boolean isFixedColumnOrder,
+                    int dividerWidth) {
                 mIsFixedOrder = isFixedColumnOrder;
                 if (parentKeyboardWidth / keyWidth < maxColumns) {
                     throw new IllegalArgumentException(
@@ -116,7 +124,9 @@
                 // Adjustment of the top row.
                 mTopRowAdjustment = mIsFixedOrder ? getFixedOrderTopRowAdjustment()
                         : getAutoOrderTopRowAdjustment();
-                mBaseWidth = mOccupiedWidth = mNumColumns * mDefaultKeyWidth;
+                mDividerWidth = dividerWidth;
+                mColumnWidth = mDefaultKeyWidth + mDividerWidth;
+                mBaseWidth = mOccupiedWidth = mNumColumns * mColumnWidth - mDividerWidth;
                 // Need to subtract the bottom row's gutter only.
                 mBaseHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight - mVerticalGap
                         + mTopPadding + mBottomPadding;
@@ -214,13 +224,13 @@
             }
 
             public int getDefaultKeyCoordX() {
-                return mLeftKeys * mDefaultKeyWidth;
+                return mLeftKeys * mColumnWidth;
             }
 
             public int getX(int n, int row) {
-                final int x = getColumnPos(n) * mDefaultKeyWidth + getDefaultKeyCoordX();
+                final int x = getColumnPos(n) * mColumnWidth + getDefaultKeyCoordX();
                 if (isTopRow(row)) {
-                    return x + mTopRowAdjustment * (mDefaultKeyWidth / 2);
+                    return x + mTopRowAdjustment * (mColumnWidth / 2);
                 }
                 return x;
             }
@@ -267,9 +277,19 @@
                 width = getMaxKeyWidth(view, parentKey, mParams.mDefaultKeyWidth);
                 height = parentKeyboard.mMostCommonKeyHeight;
             }
+            final int dividerWidth;
+            if (parentKey.needsDividersInMoreKeys()) {
+                mDivider = mResources.getDrawable(R.drawable.more_keys_divider);
+                // TODO: Drawable itself should have an alpha value.
+                mDivider.setAlpha(128);
+                dividerWidth = (int)(width * DIVIDER_RATIO);
+            } else {
+                mDivider = null;
+                dividerWidth = 0;
+            }
             mParams.setParameters(parentKey.mMoreKeys.length, parentKey.getMoreKeysColumn(),
                     width, height, parentKey.mX + parentKey.mWidth / 2, view.getMeasuredWidth(),
-                    parentKey.isFixedColumnOrderMoreKeys());
+                    parentKey.isFixedColumnOrderMoreKeys(), dividerWidth);
         }
 
         private static int getMaxKeyWidth(KeyboardView view, Key parentKey, int minKeyWidth) {
@@ -295,6 +315,21 @@
             return maxWidth;
         }
 
+        private static class MoreKeyDivider extends Key.Spacer {
+            private final Drawable mIcon;
+
+            public MoreKeyDivider(MoreKeysKeyboardParams params, Drawable icon, int x, int y) {
+                super(params, x, y, params.mDividerWidth, params.mDefaultRowHeight);
+                mIcon = icon;
+            }
+
+            @Override
+            public Drawable getIcon(KeyboardIconsSet iconSet) {
+                // KeyboardIconsSet is unused. Use the icon that has been passed to the constructor.
+                return mIcon;
+            }
+        }
+
         @Override
         public MoreKeysKeyboard build() {
             final MoreKeysKeyboardParams params = mParams;
@@ -306,11 +341,22 @@
             for (int n = 0; n < moreKeys.length; n++) {
                 final String moreKeySpec = moreKeys[n];
                 final int row = n / params.mNumColumns;
-                final Key key = new Key(mResources, params, moreKeySpec, params.getX(n, row),
-                        params.getY(row), params.mDefaultKeyWidth, params.mDefaultRowHeight,
-                        moreKeyFlags);
+                final int x = params.getX(n, row);
+                final int y = params.getY(row);
+                final Key key = new Key(mResources, params, moreKeySpec, x, y,
+                        params.mDefaultKeyWidth, params.mDefaultRowHeight, moreKeyFlags);
                 params.markAsEdgeKey(key, row);
                 params.onAddKey(key);
+
+                final int pos = params.getColumnPos(n);
+                // The "pos" value represents the offset from the default position. Negative means
+                // left of the default position.
+                if (params.mDividerWidth > 0 && pos != 0) {
+                    final int dividerX = (pos > 0) ? x - params.mDividerWidth
+                            : x + params.mDefaultKeyWidth;
+                    final Key divider = new MoreKeyDivider(params, mDivider, dividerX, y);
+                    params.onAddKey(divider);
+                }
             }
             return new MoreKeysKeyboard(params);
         }
diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
index 0bd6abe..cb1b49c 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
@@ -34,7 +34,7 @@
 public class MoreSuggestions extends Keyboard {
     public static final int SUGGESTION_CODE_BASE = 1024;
 
-    private MoreSuggestions(Builder.MoreSuggestionsParam params) {
+    MoreSuggestions(Builder.MoreSuggestionsParam params) {
         super(params);
     }
 
@@ -63,7 +63,7 @@
                 paint.setAntiAlias(true);
                 final Resources res = view.getContext().getResources();
                 mDivider = res.getDrawable(R.drawable.more_suggestions_divider);
-                // TODO: Drawable itself should has an alpha value.
+                // TODO: Drawable itself should have an alpha value.
                 mDivider.setAlpha(128);
                 mDividerWidth = mDivider.getIntrinsicWidth();
                 final int padding = (int) res.getDimension(
diff --git a/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderFixedOrderTests.java b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderFixedOrderTests.java
index afd3df4..5c6c834 100644
--- a/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderFixedOrderTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderFixedOrderTests.java
@@ -45,7 +45,7 @@
             int coordXInParnet) {
         final MoreKeysKeyboardParams params = new MoreKeysKeyboardParams();
         params.setParameters(numKeys, columnNum, WIDTH, HEIGHT, coordXInParnet, KEYBOARD_WIDTH,
-                /* isFixedOrderColumn */true);
+                /* isFixedOrderColumn */true, /* dividerWidth */0);
         return params;
     }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderTests.java b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderTests.java
index 456247b..31f0e0f 100644
--- a/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderTests.java
@@ -45,7 +45,7 @@
             int coordXInParnet) {
         final MoreKeysKeyboardParams params = new MoreKeysKeyboardParams();
         params.setParameters(numKeys, maxColumns, WIDTH, HEIGHT, coordXInParnet, KEYBOARD_WIDTH,
-                /* isFixedOrderColumn */false);
+                /* isFixedOrderColumn */false, /* dividerWidth */0);
         return params;
     }