merge in jb-release history after reset to jb-dev
diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml
index c4649e2..47619dc 100644
--- a/java/res/values-da/strings.xml
+++ b/java/res/values-da/strings.xml
@@ -45,7 +45,7 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Foreslå navne på kontakter"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Brug navne fra Kontaktpersoner til forslag og rettelser"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Aktiver fornyet rettelse"</string>
+    <string name="enable_span_insert" msgid="7204653105667167620">"Aktivér fornyet rettelse"</string>
     <string name="enable_span_insert_summary" msgid="2947317657871394467">"Angiv forslag til fornyet rettelse"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Skriv aut. med stort"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Tillægsordbøger"</string>
@@ -113,7 +113,7 @@
     <string name="select_language" msgid="3693815588777926848">"Inputsprog"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tryk igen for at gemme"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Ordbog er tilgængelig"</string>
-    <string name="prefs_enable_log" msgid="6620424505072963557">"Aktiver brugerfeedback"</string>
+    <string name="prefs_enable_log" msgid="6620424505072963557">"Aktivér brugerfeedback"</string>
     <string name="prefs_description_log" msgid="5827825607258246003">"Vær med til at forbedre denne inputmetode ved at sende anvendelsesstatistikker og rapporter om nedbrud til Google."</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tastaturtema"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engelsk (Storbritannien)"</string>
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 4bf5414..7cad3f5 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -308,14 +308,10 @@
         <attr name="visualInsetsRight" format="dimension|fraction" />
         <!-- Width of the key, in pixels or percentage of display width.
              If the value is fillRight, the actual key width will be determined to fill out the area
-             up to the right edge of the keyboard.
-             If the value is fillBoth, the actual key width will be determined to fill out the
-             area between the nearest key on the left hand side and the right edge of the keyboard.
-             -->
+             up to the right edge of the keyboard. -->
         <!-- This should be aligned with KeyboardBuilder.Row.KEYWIDTH_* -->
         <attr name="keyWidth" format="dimension|fraction|enum">
             <enum name="fillRight" value="-1" />
-            <enum name="fillBoth" value="-2" />
         </attr>
         <!-- The X-coordinate of upper right corner of this key including horizontal gap.
              If the value is negative, the origin is the right edge of the keyboard. -->
diff --git a/java/res/xml-sw600dp/key_space.xml b/java/res/xml-sw600dp/key_space.xml
index 234c803..86af89f 100644
--- a/java/res/xml-sw600dp/key_space.xml
+++ b/java/res/xml-sw600dp/key_space.xml
@@ -30,7 +30,7 @@
                 latin:keyStyle="languageSwitchKeyStyle" />
             <Key
                 latin:keyStyle="spaceKeyStyle"
-                latin:keyWidth="25.50%p" />
+                latin:keyWidth="27.0%p" />
             <Key
                 latin:keyStyle="zwnjKeyStyle" />
         </case>
@@ -40,7 +40,7 @@
         >
             <Key
                 latin:keyStyle="spaceKeyStyle"
-                latin:keyWidth="34.00%p" />
+                latin:keyWidth="36.0%p" />
             <Key
                 latin:keyStyle="zwnjKeyStyle" />
         </case>
@@ -51,13 +51,13 @@
                 latin:keyStyle="languageSwitchKeyStyle" />
             <Key
                 latin:keyStyle="spaceKeyStyle"
-                latin:keyWidth="34.00%p" />
+                latin:keyWidth="36.0%p" />
         </case>
         <!-- languageSwitchKeyEnabled="false" -->
         <default>
             <Key
                 latin:keyStyle="spaceKeyStyle"
-                latin:keyWidth="42.50%p" />
+                latin:keyWidth="45.0%p" />
         </default>
     </switch>
 </merge>
diff --git a/java/res/xml-sw600dp/keys_f1f2.xml b/java/res/xml-sw600dp/keys_f1f2.xml
index 14b7231..9d29687 100644
--- a/java/res/xml-sw600dp/keys_f1f2.xml
+++ b/java/res/xml-sw600dp/keys_f1f2.xml
@@ -27,7 +27,7 @@
         >
             <Key
                 latin:keyStyle="comKeyStyle"
-                latin:keyWidth="17.8%p" />
+                latin:keyWidth="17.0%p" />
         </case>
         <default>
             <switch>
diff --git a/java/res/xml-sw600dp/row_dvorak4.xml b/java/res/xml-sw600dp/row_dvorak4.xml
index 63ab8a8..ffc3427 100644
--- a/java/res/xml-sw600dp/row_dvorak4.xml
+++ b/java/res/xml-sw600dp/row_dvorak4.xml
@@ -22,22 +22,22 @@
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
     <Row
-        latin:keyWidth="8.9%p"
+        latin:keyWidth="9.0%p"
     >
         <Key
             latin:keyStyle="toSymbolKeyStyle"
-            latin:keyWidth="13.0%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/keys_f1f2" />
         <include
-            latin:keyXPos="30.750%p"
+            latin:keyXPos="28.0%p"
             latin:keyboardLayout="@xml/key_space" />
         <include
             latin:keyboardLayout="@xml/key_question_exclamation" />
         <include
             latin:keyboardLayout="@xml/key_dash" />
         <include
-            latin:keyXPos="-10.00%p"
+            latin:keyXPos="-9.0%p"
             latin:keyWidth="fillRight"
             latin:keyboardLayout="@xml/key_shortcut" />
     </Row>
diff --git a/java/res/xml-sw600dp/row_hebrew4.xml b/java/res/xml-sw600dp/row_hebrew4.xml
index 90441fb..114a5cc 100644
--- a/java/res/xml-sw600dp/row_hebrew4.xml
+++ b/java/res/xml-sw600dp/row_hebrew4.xml
@@ -22,20 +22,20 @@
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <Key
             latin:keyStyle="toSymbolKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/keys_f1f2" />
         <include
-            latin:keyXPos="28.75%p"
+            latin:keyXPos="28.0%p"
             latin:keyboardLayout="@xml/key_space" />
         <include
             latin:keyboardLayout="@xml/keys_comma_period" />
         <include
-            latin:keyXPos="-8.5%p"
+            latin:keyXPos="-9.0%p"
             latin:keyWidth="fillRight"
             latin:keyboardLayout="@xml/key_shortcut" />
     </Row>
diff --git a/java/res/xml-sw600dp/row_qwerty4.xml b/java/res/xml-sw600dp/row_qwerty4.xml
index 5008696..a4ba8a4 100644
--- a/java/res/xml-sw600dp/row_qwerty4.xml
+++ b/java/res/xml-sw600dp/row_qwerty4.xml
@@ -22,22 +22,22 @@
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <Key
             latin:keyStyle="toSymbolKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/keys_f1f2" />
         <include
-            latin:keyXPos="28.75%p"
+            latin:keyXPos="28.0%p"
             latin:keyboardLayout="@xml/key_space" />
         <include
             latin:keyboardLayout="@xml/key_apostrophe" />
         <include
             latin:keyboardLayout="@xml/key_dash" />
         <include
-            latin:keyXPos="-8.5%p"
+            latin:keyXPos="-9.0%p"
             latin:keyWidth="fillRight"
             latin:keyboardLayout="@xml/key_shortcut" />
     </Row>
diff --git a/java/res/xml-sw600dp/row_symbols4.xml b/java/res/xml-sw600dp/row_symbols4.xml
index a4fe5fa..20d1a7d 100644
--- a/java/res/xml-sw600dp/row_symbols4.xml
+++ b/java/res/xml-sw600dp/row_symbols4.xml
@@ -22,17 +22,17 @@
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <Key
             latin:keyStyle="toAlphaKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <Key
-            latin:keyStyle="smileyKeyStyle" />
+            latin:keyLabel="/" />
         <Key
             latin:keyLabel="\@" />
         <include
-            latin:keyXPos="28.75%p"
+            latin:keyXPos="28.0%p"
             latin:keyboardLayout="@xml/key_space" />
         <Key
             latin:keyLabel="&quot;"
@@ -40,7 +40,7 @@
         <Key
             latin:keyLabel="_" />
         <include
-            latin:keyXPos="-8.5%p"
+            latin:keyXPos="-9.0%p"
             latin:keyWidth="fillRight"
             latin:keyboardLayout="@xml/key_shortcut" />
     </Row>
diff --git a/java/res/xml-sw600dp/row_symbols_shift4.xml b/java/res/xml-sw600dp/row_symbols_shift4.xml
index ffb6e7f..fd7b370 100644
--- a/java/res/xml-sw600dp/row_symbols_shift4.xml
+++ b/java/res/xml-sw600dp/row_symbols_shift4.xml
@@ -22,18 +22,16 @@
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <Key
             latin:keyStyle="toAlphaKeyStyle"
-            latin:keyWidth="11.75%p" />
-        <Key
-            latin:keyStyle="smileyKeyStyle" />
+            latin:keyWidth="10.0%p" />
         <include
-            latin:keyXPos="28.75%p"
+            latin:keyXPos="28.0%p"
             latin:keyboardLayout="@xml/key_space" />
         <include
-            latin:keyXPos="-8.5%p"
+            latin:keyXPos="-9.0%p"
             latin:keyWidth="fillRight"
             latin:keyboardLayout="@xml/key_shortcut" />
     </Row>
diff --git a/java/res/xml-sw600dp/rows_10_10_7_symbols.xml b/java/res/xml-sw600dp/rows_10_10_7_symbols.xml
index d016eb8..44c967c 100644
--- a/java/res/xml-sw600dp/rows_10_10_7_symbols.xml
+++ b/java/res/xml-sw600dp/rows_10_10_7_symbols.xml
@@ -26,34 +26,33 @@
     <include
         latin:keyboardLayout="@xml/key_styles_currency" />
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_symbols1" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_symbols2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
         <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <Key
             latin:keyStyle="toMoreSymbolKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_symbols3" />
         <Key
             latin:keyStyle="toMoreSymbolKeyStyle"
-            latin:keyXPos="-11.75%p"
             latin:keyWidth="fillRight" />
     </Row>
     <include
diff --git a/java/res/xml-sw600dp/rows_10_10_7_symbols_shift.xml b/java/res/xml-sw600dp/rows_10_10_7_symbols_shift.xml
index d4496b8..3d3b59f 100644
--- a/java/res/xml-sw600dp/rows_10_10_7_symbols_shift.xml
+++ b/java/res/xml-sw600dp/rows_10_10_7_symbols_shift.xml
@@ -26,34 +26,33 @@
     <include
         latin:keyboardLayout="@xml/key_styles_currency" />
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_symbols_shift1" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_symbols_shift2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <Key
             latin:keyStyle="backFromMoreSymbolKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_symbols_shift3" />
         <Key
             latin:keyStyle="backFromMoreSymbolKeyStyle"
-            latin:keyXPos="-11.75%p"
             latin:keyWidth="fillRight" />
     </Row>
     <include
diff --git a/java/res/xml-sw600dp/rows_arabic.xml b/java/res/xml-sw600dp/rows_arabic.xml
index bc21854..ec7c2ad 100644
--- a/java/res/xml-sw600dp/rows_arabic.xml
+++ b/java/res/xml-sw600dp/rows_arabic.xml
@@ -24,29 +24,29 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_arabic1" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_arabic2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_arabic3"
-            latin:keyXPos="7.727%p" />
+            latin:keyXPos="4.091%p" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_qwerty4" />
diff --git a/java/res/xml-sw600dp/rows_azerty.xml b/java/res/xml-sw600dp/rows_azerty.xml
index 137c654..824ee38 100644
--- a/java/res/xml-sw600dp/rows_azerty.xml
+++ b/java/res/xml-sw600dp/rows_azerty.xml
@@ -24,37 +24,36 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_azerty1"
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_azerty2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_azerty3" />
         <include
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyXPos="-11.75%p"
             latin:keyWidth="fillRight" />
     </Row>
     <include
diff --git a/java/res/xml-sw600dp/rows_bulgarian.xml b/java/res/xml-sw600dp/rows_bulgarian.xml
index 682c72a..7253236 100644
--- a/java/res/xml-sw600dp/rows_bulgarian.xml
+++ b/java/res/xml-sw600dp/rows_bulgarian.xml
@@ -24,37 +24,36 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_bulgarian1"
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_bulgarian2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.65%p"
+        latin:keyWidth="8.182%p"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_bulgarian3" />
         <include
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyXPos="-11.75%p"
             latin:keyWidth="fillRight" />
     </Row>
     <include
diff --git a/java/res/xml-sw600dp/rows_bulgarian_bds.xml b/java/res/xml-sw600dp/rows_bulgarian_bds.xml
index 8632964..db6220e 100644
--- a/java/res/xml-sw600dp/rows_bulgarian_bds.xml
+++ b/java/res/xml-sw600dp/rows_bulgarian_bds.xml
@@ -24,30 +24,30 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_bulgarian_bds1"
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_bulgarian_bds2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.65%p"
+        latin:keyWidth="8.182%p"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_bulgarian_bds3" />
         <include
diff --git a/java/res/xml-sw600dp/rows_colemak.xml b/java/res/xml-sw600dp/rows_colemak.xml
index a943818..f7e903b 100644
--- a/java/res/xml-sw600dp/rows_colemak.xml
+++ b/java/res/xml-sw600dp/rows_colemak.xml
@@ -24,7 +24,7 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_colemak1"
@@ -33,30 +33,29 @@
             latin:keyboardLayout="@xml/key_colemak_colon" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_colemak2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_colemak3" />
         <include
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyXPos="-11.75%p"
             latin:keyWidth="fillRight" />
     </Row>
     <include
diff --git a/java/res/xml-sw600dp/rows_dvorak.xml b/java/res/xml-sw600dp/rows_dvorak.xml
index 83d1fee..2fa8eb2 100644
--- a/java/res/xml-sw600dp/rows_dvorak.xml
+++ b/java/res/xml-sw600dp/rows_dvorak.xml
@@ -24,7 +24,7 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/keys_dvorak_123" />
@@ -33,28 +33,27 @@
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_dvorak2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_dvorak3" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyXPos="-11.75%p"
             latin:keyWidth="fillRight" />
     </Row>
     <include
diff --git a/java/res/xml-sw600dp/rows_east_slavic.xml b/java/res/xml-sw600dp/rows_east_slavic.xml
index 76a6cc3..3096255 100644
--- a/java/res/xml-sw600dp/rows_east_slavic.xml
+++ b/java/res/xml-sw600dp/rows_east_slavic.xml
@@ -24,30 +24,30 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_east_slavic1"
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_east_slavic2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_east_slavic3" />
         <include
diff --git a/java/res/xml-sw600dp/rows_farsi.xml b/java/res/xml-sw600dp/rows_farsi.xml
index 9daba6d..1ce6586 100644
--- a/java/res/xml-sw600dp/rows_farsi.xml
+++ b/java/res/xml-sw600dp/rows_farsi.xml
@@ -24,31 +24,31 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_farsi1" />
     </Row>
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_farsi2" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_farsi3"
-            latin:keyXPos="7.727%p" />
+            latin:keyXPos="4.091%p" />
         <include
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_qwerty4" />
diff --git a/java/res/xml-sw600dp/rows_georgian.xml b/java/res/xml-sw600dp/rows_georgian.xml
index 89ef09f..61d3eb0 100644
--- a/java/res/xml-sw600dp/rows_georgian.xml
+++ b/java/res/xml-sw600dp/rows_georgian.xml
@@ -24,38 +24,37 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_georgian1"
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_georgian2"
-            latin:keyXPos="5.875%p" />
+            latin:keyXPos="4.5%p" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_georgian3" />
         <include
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyXPos="-11.75%p"
             latin:keyWidth="fillRight" />
     </Row>
     <include
diff --git a/java/res/xml-sw600dp/rows_greek.xml b/java/res/xml-sw600dp/rows_greek.xml
index 24cbd62..6a10228 100644
--- a/java/res/xml-sw600dp/rows_greek.xml
+++ b/java/res/xml-sw600dp/rows_greek.xml
@@ -24,7 +24,7 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/key_greek_semicolon" />
@@ -33,31 +33,30 @@
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_greek2"
-            latin:keyXPos="5.875%p" />
+            latin:keyXPos="4.5%p" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_greek3" />
         <include
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyXPos="-11.75%p"
             latin:keyWidth="fillRight" />
     </Row>
     <include
diff --git a/java/res/xml-sw600dp/rows_hebrew.xml b/java/res/xml-sw600dp/rows_hebrew.xml
index 0a7bdf1..f9e6f51 100644
--- a/java/res/xml-sw600dp/rows_hebrew.xml
+++ b/java/res/xml-sw600dp/rows_hebrew.xml
@@ -24,7 +24,7 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/key_apostrophe" />
@@ -34,23 +34,23 @@
             latin:keyboardLayout="@xml/rowkeys_hebrew1" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_hebrew2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_hebrew3"
-            latin:keyXPos="11.75%p" />
+            latin:keyXPos="10.0%p" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_hebrew4" />
diff --git a/java/res/xml-sw600dp/rows_hindi.xml b/java/res/xml-sw600dp/rows_hindi.xml
index 267e96f..9678465 100644
--- a/java/res/xml-sw600dp/rows_hindi.xml
+++ b/java/res/xml-sw600dp/rows_hindi.xml
@@ -24,30 +24,30 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_hindi1"
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_hindi2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_hindi3" />
         <include
diff --git a/java/res/xml-sw600dp/rows_nordic.xml b/java/res/xml-sw600dp/rows_nordic.xml
index 93373b6..4314403 100644
--- a/java/res/xml-sw600dp/rows_nordic.xml
+++ b/java/res/xml-sw600dp/rows_nordic.xml
@@ -24,39 +24,39 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_nordic1"
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_nordic2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <Spacer
-            latin:keyWidth="3.479%p" />
+            latin:keyWidth="3.181%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_qwerty3" />
         <include
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyXPos="-11.75%p"
+            latin:keyXPos="-10.0%p"
             latin:keyWidth="fillRight" />
     </Row>
     <include
diff --git a/java/res/xml-sw600dp/rows_pcqwerty.xml b/java/res/xml-sw600dp/rows_pcqwerty.xml
index 0c74114..fa6080a 100644
--- a/java/res/xml-sw600dp/rows_pcqwerty.xml
+++ b/java/res/xml-sw600dp/rows_pcqwerty.xml
@@ -30,7 +30,7 @@
             latin:keyboardLayout="@xml/rowkeys_pcqwerty1" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="7.0%p"
@@ -52,7 +52,7 @@
             latin:keyboardLayout="@xml/rowkeys_pcqwerty3" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="7.0%p"
diff --git a/java/res/xml-sw600dp/rows_pcqwerty_symbols.xml b/java/res/xml-sw600dp/rows_pcqwerty_symbols.xml
index dd8df4e..5e1aa63 100644
--- a/java/res/xml-sw600dp/rows_pcqwerty_symbols.xml
+++ b/java/res/xml-sw600dp/rows_pcqwerty_symbols.xml
@@ -32,7 +32,7 @@
             latin:keyboardLayout="@xml/rowkeys_pcqwerty1" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="7.0%p"
@@ -53,7 +53,7 @@
             latin:keyboardLayout="@xml/rowkeys_pcqwerty3" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="7.0%p"
diff --git a/java/res/xml-sw600dp/rows_qwerty.xml b/java/res/xml-sw600dp/rows_qwerty.xml
index 29aea3f..bac02fd 100644
--- a/java/res/xml-sw600dp/rows_qwerty.xml
+++ b/java/res/xml-sw600dp/rows_qwerty.xml
@@ -24,38 +24,37 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_qwerty1"
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_qwerty2"
-            latin:keyXPos="5.875%p" />
+            latin:keyXPos="4.5%p" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_qwerty3" />
         <include
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyXPos="-11.75%p"
             latin:keyWidth="fillRight" />
     </Row>
     <include
diff --git a/java/res/xml-sw600dp/rows_qwertz.xml b/java/res/xml-sw600dp/rows_qwertz.xml
index abbc7db..98ddd08 100644
--- a/java/res/xml-sw600dp/rows_qwertz.xml
+++ b/java/res/xml-sw600dp/rows_qwertz.xml
@@ -24,38 +24,37 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_qwertz1"
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_qwerty2"
-            latin:keyXPos="5.875%p" />
+            latin:keyXPos="4.5%p" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_qwertz3" />
         <include
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyXPos="-11.75%p"
             latin:keyWidth="fillRight" />
     </Row>
     <include
diff --git a/java/res/xml-sw600dp/rows_south_slavic.xml b/java/res/xml-sw600dp/rows_south_slavic.xml
index 68d86a9..e53a2ee 100644
--- a/java/res/xml-sw600dp/rows_south_slavic.xml
+++ b/java/res/xml-sw600dp/rows_south_slavic.xml
@@ -24,30 +24,30 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_south_slavic1"
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_south_slavic2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.727%p"
+        latin:keyWidth="8.182%p"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_south_slavic3" />
         <include
diff --git a/java/res/xml-sw600dp/rows_spanish.xml b/java/res/xml-sw600dp/rows_spanish.xml
index 8c965b2..b48ee01 100644
--- a/java/res/xml-sw600dp/rows_spanish.xml
+++ b/java/res/xml-sw600dp/rows_spanish.xml
@@ -24,37 +24,36 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_qwerty1"
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_spanish2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_qwerty3" />
         <include
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyXPos="-11.75%p"
             latin:keyWidth="fillRight" />
     </Row>
     <include
diff --git a/java/res/xml-sw600dp/rows_symbols.xml b/java/res/xml-sw600dp/rows_symbols.xml
index 57ec70d..3d0593d 100644
--- a/java/res/xml-sw600dp/rows_symbols.xml
+++ b/java/res/xml-sw600dp/rows_symbols.xml
@@ -26,35 +26,34 @@
     <include
         latin:keyboardLayout="@xml/key_styles_currency" />
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_symbols1" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_symbols2"
-            latin:keyXPos="5.875%p" />
+            latin:keyXPos="4.5%p" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
         <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <Key
             latin:keyStyle="toMoreSymbolKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_symbols3" />
         <Key
             latin:keyStyle="toMoreSymbolKeyStyle"
-            latin:keyXPos="-11.75%p"
             latin:keyWidth="fillRight" />
     </Row>
     <include
diff --git a/java/res/xml-sw600dp/rows_symbols_shift.xml b/java/res/xml-sw600dp/rows_symbols_shift.xml
index c46661e..0050c0c 100644
--- a/java/res/xml-sw600dp/rows_symbols_shift.xml
+++ b/java/res/xml-sw600dp/rows_symbols_shift.xml
@@ -26,35 +26,34 @@
     <include
         latin:keyboardLayout="@xml/key_styles_currency" />
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_symbols_shift1" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_symbols_shift2"
-            latin:keyXPos="5.875%p" />
+            latin:keyXPos="4.5%p" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.5%p"
+        latin:keyWidth="9.0%p"
     >
         <Key
             latin:keyStyle="backFromMoreSymbolKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_symbols_shift3" />
         <Key
             latin:keyStyle="backFromMoreSymbolKeyStyle"
-            latin:keyXPos="-11.75%p"
             latin:keyWidth="fillRight" />
     </Row>
     <include
diff --git a/java/res/xml-sw600dp/rows_thai.xml b/java/res/xml-sw600dp/rows_thai.xml
index c387081..c1fe55b 100644
--- a/java/res/xml-sw600dp/rows_thai.xml
+++ b/java/res/xml-sw600dp/rows_thai.xml
@@ -24,38 +24,38 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="7.354%p"
+        latin:keyWidth="7.5%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_thai1"
-            latin:keyXPos="4.396%p" />
+            latin:keyXPos="3.75%p" />
         <Key
             latin:keyStyle="deleteKeyStyle"
             latin:keyWidth="fillRight" />
         </Row>
     <Row
-        latin:keyWidth="7.354%p"
+        latin:keyWidth="7.5%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_thai2"
             latin:keyXPos="0.719%p" />
     </Row>
     <Row
-        latin:keyWidth="7.354%p"
+        latin:keyWidth="7.5%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_thai3"
-            latin:keyXPos="4.396%p" />
+            latin:keyXPos="3.75%p" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.354%p"
+        latin:keyWidth="7.5%p"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="11.75%p" />
+            latin:keyWidth="10.0%p" />
         <include
             latin:keyboardLayout="@xml/rowkeys_thai4" />
         <include
diff --git a/java/res/xml-sw768dp/key_space.xml b/java/res/xml-sw768dp/key_space.xml
index 36326c4..8968f08 100644
--- a/java/res/xml-sw768dp/key_space.xml
+++ b/java/res/xml-sw768dp/key_space.xml
@@ -27,7 +27,7 @@
         >
             <Key
                 latin:keyStyle="spaceKeyStyle"
-                latin:keyWidth="29.453%p" />
+                latin:keyWidth="32.188%p" />
             <!-- U+200C: "" ZERO WIDTH NON-JOINER
                  U+200D: "" ZERO WIDTH JOINER -->
             <Key
@@ -36,7 +36,7 @@
         <default>
             <Key
                 latin:keyStyle="spaceKeyStyle"
-                latin:keyWidth="37.500%p" />
+                latin:keyWidth="40.235%p" />
         </default>
     </switch>
 </merge>
diff --git a/java/res/xml-sw768dp/row_dvorak4.xml b/java/res/xml-sw768dp/row_dvorak4.xml
index 251b4f5..ebe517d 100644
--- a/java/res/xml-sw768dp/row_dvorak4.xml
+++ b/java/res/xml-sw768dp/row_dvorak4.xml
@@ -27,10 +27,10 @@
         <include
             latin:keyboardLayout="@xml/key_settings" />
         <include
-            latin:keyXPos="15.157%p"
+            latin:keyXPos="13.829%p"
             latin:keyboardLayout="@xml/keys_f1f2" />
         <include
-            latin:keyXPos="31.250%p"
+            latin:keyXPos="29.923%p"
             latin:keyboardLayout="@xml/key_space" />
         <include
             latin:keyboardLayout="@xml/key_question_exclamation" />
diff --git a/java/res/xml-sw768dp/row_hebrew4.xml b/java/res/xml-sw768dp/row_hebrew4.xml
index 8ec7ea7..477fd0d 100644
--- a/java/res/xml-sw768dp/row_hebrew4.xml
+++ b/java/res/xml-sw768dp/row_hebrew4.xml
@@ -27,9 +27,10 @@
         <include
             latin:keyboardLayout="@xml/key_settings" />
         <include
-            latin:keyXPos="15.157%p"
+            latin:keyXPos="13.829%p"
             latin:keyboardLayout="@xml/keys_f1f2" />
         <include
+            latin:keyXPos="29.923%p"
             latin:keyboardLayout="@xml/key_space" />
         <include
             latin:keyboardLayout="@xml/keys_comma_period" />
diff --git a/java/res/xml-sw768dp/row_qwerty4.xml b/java/res/xml-sw768dp/row_qwerty4.xml
index 0cf964f..32a6476 100644
--- a/java/res/xml-sw768dp/row_qwerty4.xml
+++ b/java/res/xml-sw768dp/row_qwerty4.xml
@@ -27,10 +27,10 @@
         <include
             latin:keyboardLayout="@xml/key_settings" />
         <include
-            latin:keyXPos="15.157%p"
+            latin:keyXPos="13.829%p"
             latin:keyboardLayout="@xml/keys_f1f2" />
         <include
-            latin:keyXPos="31.250%p"
+            latin:keyXPos="29.923%p"
             latin:keyboardLayout="@xml/key_space" />
         <include
             latin:keyboardLayout="@xml/key_apostrophe" />
diff --git a/java/res/xml-sw768dp/row_symbols4.xml b/java/res/xml-sw768dp/row_symbols4.xml
index 167fc5e..bd85b40 100644
--- a/java/res/xml-sw768dp/row_symbols4.xml
+++ b/java/res/xml-sw768dp/row_symbols4.xml
@@ -28,11 +28,11 @@
             latin:keyboardLayout="@xml/key_settings" />
         <Key
             latin:keyLabel="/"
-            latin:keyXPos="15.157%p" />
+            latin:keyXPos="13.829%p" />
         <Key
             latin:keyLabel="\@" />
         <include
-            latin:keyXPos="31.250%p"
+            latin:keyXPos="29.923%p"
             latin:keyboardLayout="@xml/key_space" />
         <Key
             latin:keyLabel="&quot;"
diff --git a/java/res/xml-sw768dp/row_symbols_shift4.xml b/java/res/xml-sw768dp/row_symbols_shift4.xml
index 683ec43..82c1d17 100644
--- a/java/res/xml-sw768dp/row_symbols_shift4.xml
+++ b/java/res/xml-sw768dp/row_symbols_shift4.xml
@@ -27,7 +27,7 @@
         <include
             latin:keyboardLayout="@xml/key_settings" />
         <include
-            latin:keyXPos="31.250%p"
+            latin:keyXPos="29.923%p"
             latin:keyboardLayout="@xml/key_space" />
         <include
             latin:keyXPos="-8.047%p"
diff --git a/java/res/xml-sw768dp/rows_10_10_7_symbols.xml b/java/res/xml-sw768dp/rows_10_10_7_symbols.xml
index 44f0964..d9b0d23 100644
--- a/java/res/xml-sw768dp/rows_10_10_7_symbols.xml
+++ b/java/res/xml-sw768dp/rows_10_10_7_symbols.xml
@@ -49,7 +49,7 @@
             latin:keyboardLayout="@xml/rowkeys_symbols2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.047%p"
@@ -62,7 +62,7 @@
         <Key
             latin:keyStyle="toMoreSymbolKeyStyle"
             latin:keyXPos="-13.750%p"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_symbols4" />
diff --git a/java/res/xml-sw768dp/rows_10_10_7_symbols_shift.xml b/java/res/xml-sw768dp/rows_10_10_7_symbols_shift.xml
index bea0d9c..a317dbf 100644
--- a/java/res/xml-sw768dp/rows_10_10_7_symbols_shift.xml
+++ b/java/res/xml-sw768dp/rows_10_10_7_symbols_shift.xml
@@ -36,7 +36,7 @@
             latin:keyboardLayout="@xml/rowkeys_symbols_shift1" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.125%p"
@@ -49,7 +49,7 @@
             latin:keyboardLayout="@xml/rowkeys_symbols_shift2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.047%p"
@@ -62,7 +62,7 @@
         <Key
             latin:keyStyle="backFromMoreSymbolKeyStyle"
             latin:keyXPos="-13.750%p"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_symbols_shift4" />
diff --git a/java/res/xml-sw768dp/rows_arabic.xml b/java/res/xml-sw768dp/rows_arabic.xml
index eaa64e5..8b05d93 100644
--- a/java/res/xml-sw768dp/rows_arabic.xml
+++ b/java/res/xml-sw768dp/rows_arabic.xml
@@ -34,10 +34,10 @@
             latin:keyboardLayout="@xml/rowkeys_arabic1" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.375%p"
+        latin:keyWidth="7.227%p"
     >
         <Key
             latin:keyStyle="toSymbolKeyStyle"
@@ -47,10 +47,10 @@
             latin:keyboardLayout="@xml/rowkeys_arabic2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.375%p"
+        latin:keyWidth="7.227%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_arabic3"
diff --git a/java/res/xml-sw768dp/rows_azerty.xml b/java/res/xml-sw768dp/rows_azerty.xml
index 1fc1a06..dcc403b 100644
--- a/java/res/xml-sw768dp/rows_azerty.xml
+++ b/java/res/xml-sw768dp/rows_azerty.xml
@@ -35,7 +35,7 @@
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.125%p"
@@ -48,7 +48,7 @@
             latin:keyboardLayout="@xml/rowkeys_azerty2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.047%p"
@@ -62,7 +62,7 @@
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_qwerty4" />
diff --git a/java/res/xml-sw768dp/rows_bulgarian.xml b/java/res/xml-sw768dp/rows_bulgarian.xml
index cb05fd5..6453414 100644
--- a/java/res/xml-sw768dp/rows_bulgarian.xml
+++ b/java/res/xml-sw768dp/rows_bulgarian.xml
@@ -24,7 +24,7 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="7.186%p"
+        latin:keyWidth="7.375%p"
     >
         <Key
             latin:keyStyle="tabKeyStyle"
@@ -35,10 +35,10 @@
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.186%p"
+        latin:keyWidth="7.227%p"
     >
         <Key
             latin:keyStyle="toSymbolKeyStyle"
@@ -48,10 +48,10 @@
             latin:keyboardLayout="@xml/rowkeys_bulgarian2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.125%p"
+        latin:keyWidth="7.186%p"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
@@ -62,7 +62,7 @@
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_qwerty4" />
diff --git a/java/res/xml-sw768dp/rows_bulgarian_bds.xml b/java/res/xml-sw768dp/rows_bulgarian_bds.xml
index 31343d2..8acb4d2 100644
--- a/java/res/xml-sw768dp/rows_bulgarian_bds.xml
+++ b/java/res/xml-sw768dp/rows_bulgarian_bds.xml
@@ -24,7 +24,7 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="7.000%p"
+        latin:keyWidth="7.375%p"
     >
         <Key
             latin:keyStyle="tabKeyStyle"
@@ -35,10 +35,10 @@
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.000%p"
+        latin:keyWidth="7.227%p"
     >
         <Key
             latin:keyStyle="toSymbolKeyStyle"
@@ -48,7 +48,7 @@
             latin:keyboardLayout="@xml/rowkeys_bulgarian_bds2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="7.000%p"
@@ -62,7 +62,7 @@
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_qwerty4" />
diff --git a/java/res/xml-sw768dp/rows_colemak.xml b/java/res/xml-sw768dp/rows_colemak.xml
index 01ebead..db9b0c2 100644
--- a/java/res/xml-sw768dp/rows_colemak.xml
+++ b/java/res/xml-sw768dp/rows_colemak.xml
@@ -37,7 +37,7 @@
             latin:keyboardLayout="@xml/key_colemak_colon" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.125%p"
@@ -50,7 +50,7 @@
             latin:keyboardLayout="@xml/rowkeys_colemak2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.047%p"
@@ -64,7 +64,7 @@
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_qwerty4" />
diff --git a/java/res/xml-sw768dp/rows_dvorak.xml b/java/res/xml-sw768dp/rows_dvorak.xml
index 91d0f1b..9416478 100644
--- a/java/res/xml-sw768dp/rows_dvorak.xml
+++ b/java/res/xml-sw768dp/rows_dvorak.xml
@@ -37,7 +37,7 @@
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.125%p"
@@ -50,7 +50,7 @@
             latin:keyboardLayout="@xml/rowkeys_dvorak2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.047%p"
@@ -62,7 +62,7 @@
             latin:keyboardLayout="@xml/rowkeys_dvorak3" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_dvorak4" />
diff --git a/java/res/xml-sw768dp/rows_east_slavic.xml b/java/res/xml-sw768dp/rows_east_slavic.xml
index 480881b..0316c76 100644
--- a/java/res/xml-sw768dp/rows_east_slavic.xml
+++ b/java/res/xml-sw768dp/rows_east_slavic.xml
@@ -38,7 +38,7 @@
             latin:keyLabel="&#x044A;" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="7.000%p"
@@ -51,7 +51,7 @@
             latin:keyboardLayout="@xml/rowkeys_east_slavic2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="7.000%p"
@@ -65,7 +65,7 @@
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_qwerty4" />
diff --git a/java/res/xml-sw768dp/rows_farsi.xml b/java/res/xml-sw768dp/rows_farsi.xml
index 8a70df9..28031bb 100644
--- a/java/res/xml-sw768dp/rows_farsi.xml
+++ b/java/res/xml-sw768dp/rows_farsi.xml
@@ -24,7 +24,7 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="7.125%p"
+        latin:keyWidth="7.375%p"
     >
         <Key
             latin:keyStyle="tabKeyStyle"
@@ -34,7 +34,7 @@
             latin:keyboardLayout="@xml/rowkeys_farsi1" />
     </Row>
     <Row
-        latin:keyWidth="7.125%p"
+        latin:keyWidth="7.227%p"
     >
         <Key
             latin:keyStyle="toSymbolKeyStyle"
@@ -44,10 +44,10 @@
             latin:keyboardLayout="@xml/rowkeys_farsi2" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.375%p"
+        latin:keyWidth="7.186%p"
     >
         <include
             latin:keyboardLayout="@xml/rowkeys_farsi3"
@@ -56,7 +56,7 @@
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_qwerty4" />
diff --git a/java/res/xml-sw768dp/rows_georgian.xml b/java/res/xml-sw768dp/rows_georgian.xml
index 3805b5d..74f1a07 100644
--- a/java/res/xml-sw768dp/rows_georgian.xml
+++ b/java/res/xml-sw768dp/rows_georgian.xml
@@ -35,7 +35,7 @@
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth"/>
+            latin:keyWidth="fillRight"/>
     </Row>
     <Row
         latin:keyWidth="8.125%p"
@@ -48,7 +48,7 @@
             latin:keyboardLayout="@xml/rowkeys_georgian2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.047%p"
@@ -62,8 +62,7 @@
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyXPos="-13.750%p"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_qwerty4" />
diff --git a/java/res/xml-sw768dp/rows_greek.xml b/java/res/xml-sw768dp/rows_greek.xml
index cf2fa40..aebe129 100644
--- a/java/res/xml-sw768dp/rows_greek.xml
+++ b/java/res/xml-sw768dp/rows_greek.xml
@@ -37,7 +37,7 @@
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth"/>
+            latin:keyWidth="fillRight"/>
     </Row>
     <Row
         latin:keyWidth="8.125%p"
@@ -50,7 +50,7 @@
             latin:keyboardLayout="@xml/rowkeys_greek2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.047%p"
@@ -64,7 +64,7 @@
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
    <include
         latin:keyboardLayout="@xml/row_qwerty4" />
diff --git a/java/res/xml-sw768dp/rows_hebrew.xml b/java/res/xml-sw768dp/rows_hebrew.xml
index beb59b4..e588b83 100644
--- a/java/res/xml-sw768dp/rows_hebrew.xml
+++ b/java/res/xml-sw768dp/rows_hebrew.xml
@@ -38,7 +38,7 @@
             latin:keyboardLayout="@xml/rowkeys_hebrew1" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.125%p"
@@ -51,7 +51,7 @@
             latin:keyboardLayout="@xml/rowkeys_hebrew2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
         </Row>
     <Row
         latin:keyWidth="8.047%p"
diff --git a/java/res/xml-sw768dp/rows_hindi.xml b/java/res/xml-sw768dp/rows_hindi.xml
index 86e925f..510772b 100644
--- a/java/res/xml-sw768dp/rows_hindi.xml
+++ b/java/res/xml-sw768dp/rows_hindi.xml
@@ -24,7 +24,7 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="7.333%p"
+        latin:keyWidth="7.375%p"
     >
         <Key
             latin:keyStyle="tabKeyStyle"
@@ -35,10 +35,10 @@
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.186%p"
+        latin:keyWidth="7.227%p"
     >
         <Key
             latin:keyStyle="toSymbolKeyStyle"
@@ -48,10 +48,10 @@
             latin:keyboardLayout="@xml/rowkeys_hindi2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.040%p"
+        latin:keyWidth="7.000%p"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
@@ -62,7 +62,7 @@
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_qwerty4" />
diff --git a/java/res/xml-sw768dp/rows_nordic.xml b/java/res/xml-sw768dp/rows_nordic.xml
index 9a45251..06591a6 100644
--- a/java/res/xml-sw768dp/rows_nordic.xml
+++ b/java/res/xml-sw768dp/rows_nordic.xml
@@ -35,7 +35,7 @@
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="7.227%p"
@@ -48,7 +48,7 @@
             latin:keyboardLayout="@xml/rowkeys_nordic2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="7.227%p"
diff --git a/java/res/xml-sw768dp/rows_pcqwerty.xml b/java/res/xml-sw768dp/rows_pcqwerty.xml
index c14fb12..a844728 100644
--- a/java/res/xml-sw768dp/rows_pcqwerty.xml
+++ b/java/res/xml-sw768dp/rows_pcqwerty.xml
@@ -30,7 +30,7 @@
             latin:keyboardLayout="@xml/rowkeys_pcqwerty1" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="7.0%p"
@@ -52,7 +52,7 @@
             latin:keyboardLayout="@xml/rowkeys_pcqwerty3" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="7.0%p"
@@ -64,7 +64,7 @@
             latin:keyboardLayout="@xml/rowkeys_pcqwerty4" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_pcqwerty5" />
diff --git a/java/res/xml-sw768dp/rows_pcqwerty_symbols.xml b/java/res/xml-sw768dp/rows_pcqwerty_symbols.xml
index faa9d8a..956da97 100644
--- a/java/res/xml-sw768dp/rows_pcqwerty_symbols.xml
+++ b/java/res/xml-sw768dp/rows_pcqwerty_symbols.xml
@@ -32,7 +32,7 @@
             latin:keyboardLayout="@xml/rowkeys_pcqwerty1" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="7.0%p"
@@ -53,7 +53,7 @@
             latin:keyboardLayout="@xml/rowkeys_pcqwerty3" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="7.0%p"
diff --git a/java/res/xml-sw768dp/rows_qwerty.xml b/java/res/xml-sw768dp/rows_qwerty.xml
index edfb401..a1deabd 100644
--- a/java/res/xml-sw768dp/rows_qwerty.xml
+++ b/java/res/xml-sw768dp/rows_qwerty.xml
@@ -35,7 +35,7 @@
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth"/>
+            latin:keyWidth="fillRight"/>
     </Row>
     <Row
         latin:keyWidth="8.125%p"
@@ -48,7 +48,7 @@
             latin:keyboardLayout="@xml/rowkeys_qwerty2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.047%p"
@@ -62,8 +62,7 @@
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyXPos="-13.750%p"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_qwerty4" />
diff --git a/java/res/xml-sw768dp/rows_qwertz.xml b/java/res/xml-sw768dp/rows_qwertz.xml
index 7e75506..801dd38 100644
--- a/java/res/xml-sw768dp/rows_qwertz.xml
+++ b/java/res/xml-sw768dp/rows_qwertz.xml
@@ -35,7 +35,7 @@
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth"/>
+            latin:keyWidth="fillRight"/>
     </Row>
     <Row
         latin:keyWidth="8.125%p"
@@ -48,7 +48,7 @@
             latin:keyboardLayout="@xml/rowkeys_qwerty2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.047%p"
@@ -62,8 +62,7 @@
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyXPos="-13.750%p"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_qwerty4" />
diff --git a/java/res/xml-sw768dp/rows_south_slavic.xml b/java/res/xml-sw768dp/rows_south_slavic.xml
index 7ea0ff4..b556853 100644
--- a/java/res/xml-sw768dp/rows_south_slavic.xml
+++ b/java/res/xml-sw768dp/rows_south_slavic.xml
@@ -24,7 +24,7 @@
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
     <Row
-        latin:keyWidth="7.000%p"
+        latin:keyWidth="7.375%p"
     >
         <Key
             latin:keyStyle="tabKeyStyle"
@@ -35,10 +35,10 @@
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="7.000%p"
+        latin:keyWidth="7.227%p"
     >
         <Key
             latin:keyStyle="toSymbolKeyStyle"
@@ -48,7 +48,7 @@
             latin:keyboardLayout="@xml/rowkeys_south_slavic2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="7.000%p"
@@ -62,7 +62,7 @@
             latin:keyboardLayout="@xml/keys_comma_period" />
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_qwerty4" />
diff --git a/java/res/xml-sw768dp/rows_spanish.xml b/java/res/xml-sw768dp/rows_spanish.xml
index fc3388d..8b80332 100644
--- a/java/res/xml-sw768dp/rows_spanish.xml
+++ b/java/res/xml-sw768dp/rows_spanish.xml
@@ -35,7 +35,7 @@
             latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth"/>
+            latin:keyWidth="fillRight"/>
     </Row>
     <Row
         latin:keyWidth="8.125%p"
@@ -48,7 +48,7 @@
             latin:keyboardLayout="@xml/rowkeys_spanish2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.047%p"
@@ -63,7 +63,7 @@
         <Key
             latin:keyStyle="shiftKeyStyle"
             latin:keyXPos="-13.750%p"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_qwerty4" />
diff --git a/java/res/xml-sw768dp/rows_symbols.xml b/java/res/xml-sw768dp/rows_symbols.xml
index fcc624f..efd7735 100644
--- a/java/res/xml-sw768dp/rows_symbols.xml
+++ b/java/res/xml-sw768dp/rows_symbols.xml
@@ -49,7 +49,7 @@
             latin:keyboardLayout="@xml/rowkeys_symbols2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.047%p"
@@ -61,8 +61,7 @@
             latin:keyboardLayout="@xml/rowkeys_symbols3" />
         <Key
             latin:keyStyle="toMoreSymbolKeyStyle"
-            latin:keyXPos="-13.750%p"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_symbols4" />
diff --git a/java/res/xml-sw768dp/rows_symbols_shift.xml b/java/res/xml-sw768dp/rows_symbols_shift.xml
index 1d13bb1..fd1b93d 100644
--- a/java/res/xml-sw768dp/rows_symbols_shift.xml
+++ b/java/res/xml-sw768dp/rows_symbols_shift.xml
@@ -36,7 +36,7 @@
             latin:keyboardLayout="@xml/rowkeys_symbols_shift1" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.125%p"
@@ -49,7 +49,7 @@
             latin:keyboardLayout="@xml/rowkeys_symbols_shift2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.047%p"
@@ -61,8 +61,7 @@
             latin:keyboardLayout="@xml/rowkeys_symbols_shift3" />
         <Key
             latin:keyStyle="backFromMoreSymbolKeyStyle"
-            latin:keyXPos="-13.750%p"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_symbols_shift4" />
diff --git a/java/res/xml-sw768dp/rows_thai.xml b/java/res/xml-sw768dp/rows_thai.xml
index c7720c9..7721bc5 100644
--- a/java/res/xml-sw768dp/rows_thai.xml
+++ b/java/res/xml-sw768dp/rows_thai.xml
@@ -31,7 +31,7 @@
             latin:keyXPos="11.508%p" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth"/>
+            latin:keyWidth="fillRight"/>
     </Row>
     <Row
         latin:keyWidth="7.079%p"
@@ -54,7 +54,7 @@
             latin:keyboardLayout="@xml/rowkeys_thai3" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="7.181%p"
diff --git a/java/res/xml-sw768dp/rows_thai_symbols.xml b/java/res/xml-sw768dp/rows_thai_symbols.xml
index b3f60f5..5285141 100644
--- a/java/res/xml-sw768dp/rows_thai_symbols.xml
+++ b/java/res/xml-sw768dp/rows_thai_symbols.xml
@@ -56,7 +56,7 @@
             latin:keyboardLayout="@xml/rowkeys_symbols2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.047%p"
@@ -69,7 +69,7 @@
         <Key
             latin:keyStyle="toMoreSymbolKeyStyle"
             latin:keyXPos="-13.750%p"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_symbols4" />
diff --git a/java/res/xml-sw768dp/rows_thai_symbols_shift.xml b/java/res/xml-sw768dp/rows_thai_symbols_shift.xml
index 573e0e3..9d2694b 100644
--- a/java/res/xml-sw768dp/rows_thai_symbols_shift.xml
+++ b/java/res/xml-sw768dp/rows_thai_symbols_shift.xml
@@ -33,7 +33,7 @@
             latin:keyXPos="7.969%p" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.282%p"
@@ -56,7 +56,7 @@
             latin:keyboardLayout="@xml/rowkeys_symbols_shift2" />
         <Key
             latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <Row
         latin:keyWidth="8.047%p"
@@ -69,7 +69,7 @@
         <Key
             latin:keyStyle="backFromMoreSymbolKeyStyle"
             latin:keyXPos="-13.750%p"
-            latin:keyWidth="fillBoth" />
+            latin:keyWidth="fillRight" />
     </Row>
     <include
         latin:keyboardLayout="@xml/row_symbols_shift4" />
diff --git a/java/res/xml/rows_georgian.xml b/java/res/xml/rows_georgian.xml
index 9bddfc7..8c81dd0 100644
--- a/java/res/xml/rows_georgian.xml
+++ b/java/res/xml/rows_georgian.xml
@@ -47,7 +47,7 @@
             latin:keyboardLayout="@xml/rowkeys_georgian3" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth"
+            latin:keyWidth="fillRight"
             latin:visualInsetsLeft="1%p" />
     </Row>
     <include
diff --git a/java/res/xml/rows_qwerty.xml b/java/res/xml/rows_qwerty.xml
index 716d106..cdd4203 100644
--- a/java/res/xml/rows_qwerty.xml
+++ b/java/res/xml/rows_qwerty.xml
@@ -47,7 +47,7 @@
             latin:keyboardLayout="@xml/rowkeys_qwerty3" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth"
+            latin:keyWidth="fillRight"
             latin:visualInsetsLeft="1%p" />
     </Row>
     <include
diff --git a/java/res/xml/rows_spanish.xml b/java/res/xml/rows_spanish.xml
index b311297..ecda4a4 100644
--- a/java/res/xml/rows_spanish.xml
+++ b/java/res/xml/rows_spanish.xml
@@ -46,7 +46,7 @@
             latin:keyboardLayout="@xml/rowkeys_qwerty3" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillBoth"
+            latin:keyWidth="fillRight"
             latin:visualInsetsLeft="1%p" />
     </Row>
     <include
diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
index 25afef1..a0f48d2 100644
--- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
+++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
@@ -108,6 +108,7 @@
         if (!dictionaryAvailable || TextUtils.isEmpty(pickedWord)
                 || CONSTRUCTOR_SuggestionSpan == null
                 || suggestedWords == null || suggestedWords.size() == 0
+                || suggestedWords.mIsPrediction || suggestedWords.mIsPunctuationSuggestions
                 || OBJ_SUGGESTIONS_MAX_SIZE == null) {
             return pickedWord;
         }
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 28855f5..bd3b0e1 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -511,7 +511,6 @@
             // keyWidth enum constants
             private static final int KEYWIDTH_NOT_ENUM = 0;
             private static final int KEYWIDTH_FILL_RIGHT = -1;
-            private static final int KEYWIDTH_FILL_BOTH = -2;
 
             private final Params mParams;
             /** Default width of a key in this row. */
@@ -576,11 +575,6 @@
             public float getKeyX(TypedArray keyAttr) {
                 final int widthType = Builder.getEnumValue(keyAttr,
                         R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM);
-                if (widthType == KEYWIDTH_FILL_BOTH) {
-                    // If keyWidth is fillBoth, the key width should start right after the nearest
-                    // key on the left hand side.
-                    return mCurrentX;
-                }
 
                 final int keyboardRightEdge = mParams.mOccupiedWidth
                         - mParams.mHorizontalEdgesPadding;
@@ -610,14 +604,10 @@
                         R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM);
                 switch (widthType) {
                 case KEYWIDTH_FILL_RIGHT:
-                case KEYWIDTH_FILL_BOTH:
                     final int keyboardRightEdge =
                             mParams.mOccupiedWidth - mParams.mHorizontalEdgesPadding;
                     // If keyWidth is fillRight, the actual key width will be determined to fill
                     // out the area up to the right edge of the keyboard.
-                    // If keyWidth is fillBoth, the actual key width will be determined to fill out
-                    // the area between the nearest key on the left hand side and the right edge of
-                    // the keyboard.
                     return keyboardRightEdge - keyXPos;
                 default: // KEYWIDTH_NOT_ENUM
                     return Builder.getDimensionOrFraction(keyAttr,
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
index be807ab..0bde2c0 100644
--- a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
+++ b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
@@ -131,6 +131,7 @@
 
     private interface SubtypeDialogProxy {
         public void onRemovePressed(SubtypePreference subtypePref);
+        public void onAddPressed(SubtypePreference subtypePref);
         public SubtypeLocaleAdapter getSubtypeLocaleAdapter();
         public KeyboardLayoutSetAdapter getKeyboardLayoutSetAdapter();
     }
@@ -241,6 +242,7 @@
             super.onClick(dialog, which);
             switch (which) {
             case DialogInterface.BUTTON_POSITIVE:
+                final boolean addPressed = isIncomplete();
                 final SubtypeLocaleItem locale =
                         (SubtypeLocaleItem) mSubtypeLocaleSpinner.getSelectedItem();
                 final KeyboardLayoutSetItem layout =
@@ -249,6 +251,9 @@
                         locale.first, layout.first, ASCII_CAPABLE);
                 setSubtype(subtype);
                 notifyChanged();
+                if (addPressed) {
+                    mProxy.onAddPressed(this);
+                }
                 break;
             case DialogInterface.BUTTON_NEUTRAL:
                 // Nothing to do
@@ -391,6 +396,11 @@
         }
 
         @Override
+        public void onAddPressed(SubtypePreference subtypePref) {
+            mIsAddingNewSubtype = false;
+        }
+
+        @Override
         public SubtypeLocaleAdapter getSubtypeLocaleAdapter() {
             return mSubtypeLocaleAdapter;
         }
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index a644ec0..cc20f42 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -17,6 +17,7 @@
 package com.android.inputmethod.latin;
 
 import android.content.Context;
+import android.text.TextUtils;
 
 import com.android.inputmethod.keyboard.ProximityInfo;
 
@@ -84,6 +85,7 @@
             int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength, int maxWords);
     private native void closeNative(long dict);
     private native boolean isValidWordNative(long dict, int[] word, int wordLength);
+    private native boolean isValidBigramNative(long dict, int[] word1, int[] word2);
     private native int getSuggestionsNative(long dict, long proximityInfo, int[] xCoordinates,
             int[] yCoordinates, int[] inputCodes, int codesSize, int[] prevWordForBigrams,
             boolean useFullEditDistance, char[] outputChars, int[] scores);
@@ -204,6 +206,15 @@
         return isValidWordNative(mNativeDict, chars, chars.length);
     }
 
+    // TODO: Add a batch process version (isValidBigramMultiple?) to avoid excessive numbers of jni
+    // calls when checking for changes in an entire dictionary.
+    public boolean isValidBigram(CharSequence word1, CharSequence word2) {
+        if (TextUtils.isEmpty(word1) || TextUtils.isEmpty(word2)) return false;
+        int[] chars1 = StringUtils.toCodePointArray(word1.toString());
+        int[] chars2 = StringUtils.toCodePointArray(word2.toString());
+        return isValidBigramNative(mNativeDict, chars1, chars2);
+    }
+
     @Override
     public synchronized void close() {
         closeInternal();
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 65f97e9..22787c2 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -18,6 +18,7 @@
 import android.content.Context;
 import android.database.ContentObserver;
 import android.database.Cursor;
+import android.os.SystemClock;
 import android.provider.BaseColumns;
 import android.provider.ContactsContract.Contacts;
 import android.text.TextUtils;
@@ -30,18 +31,27 @@
 public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
 
     private static final String[] PROJECTION = {BaseColumns._ID, Contacts.DISPLAY_NAME,};
+    private static final String[] PROJECTION_ID_ONLY = {BaseColumns._ID};
 
     private static final String TAG = ContactsBinaryDictionary.class.getSimpleName();
     private static final String NAME = "contacts";
 
+    private static boolean DEBUG = false;
+
     /**
      * Frequency for contacts information into the dictionary
      */
     private static final int FREQUENCY_FOR_CONTACTS = 40;
     private static final int FREQUENCY_FOR_CONTACTS_BIGRAM = 90;
 
+    /** The maximum number of contacts that this dictionary supports. */
+    private static final int MAX_CONTACT_COUNT = 10000;
+
     private static final int INDEX_NAME = 1;
 
+    /** The number of contacts in the most recent dictionary rebuild. */
+    static private int sContactCountAtLastRebuild = 0;
+
     private ContentObserver mObserver;
 
     /**
@@ -98,6 +108,7 @@
             if (cursor != null) {
                 try {
                     if (cursor.moveToFirst()) {
+                        sContactCountAtLastRebuild = getContactCount();
                         addWords(cursor);
                     }
                 } finally {
@@ -125,15 +136,28 @@
 
     private void addWords(Cursor cursor) {
         clearFusionDictionary();
-        while (!cursor.isAfterLast()) {
+        int count = 0;
+        while (!cursor.isAfterLast() && count < MAX_CONTACT_COUNT) {
             String name = cursor.getString(INDEX_NAME);
-            if (name != null && -1 == name.indexOf('@')) {
+            if (isValidName(name)) {
                 addName(name);
+                ++count;
             }
             cursor.moveToNext();
         }
     }
 
+    private int getContactCount() {
+        // TODO: consider switching to a rawQuery("select count(*)...") on the database if
+        // performance is a bottleneck.
+        final Cursor cursor = mContext.getContentResolver().query(
+                Contacts.CONTENT_URI, PROJECTION_ID_ONLY, null, null, null);
+        if (cursor != null) {
+            return cursor.getCount();
+        }
+        return 0;
+    }
+
     /**
      * Adds the words in a name (e.g., firstname/lastname) to the binary dictionary along with their
      * bigrams depending on locale.
@@ -144,16 +168,9 @@
         // TODO: Better tokenization for non-Latin writing systems
         for (int i = 0; i < len; i++) {
             if (Character.isLetter(name.codePointAt(i))) {
-                int j;
-                for (j = i + 1; j < len; j++) {
-                    final int codePoint = name.codePointAt(j);
-                    if (!(codePoint == Keyboard.CODE_DASH || codePoint == Keyboard.CODE_SINGLE_QUOTE
-                            || Character.isLetter(codePoint))) {
-                        break;
-                    }
-                }
-                String word = name.substring(i, j);
-                i = j - 1;
+                int end = getWordEndPosition(name, len, i);
+                String word = name.substring(i, end);
+                i = end - 1;
                 // Don't add single letter words, possibly confuses
                 // capitalization of i.
                 final int wordLen = word.codePointCount(0, word.length());
@@ -169,4 +186,100 @@
             }
         }
     }
+
+    /**
+     * Returns the index of the last letter in the word, starting from position startIndex.
+     */
+    private static int getWordEndPosition(String string, int len, int startIndex) {
+        int end;
+        int cp = 0;
+        for (end = startIndex + 1; end < len; end += Character.charCount(cp)) {
+            cp = string.codePointAt(end);
+            if (!(cp == Keyboard.CODE_DASH || cp == Keyboard.CODE_SINGLE_QUOTE
+                    || Character.isLetter(cp))) {
+                break;
+            }
+        }
+        return end;
+    }
+
+    @Override
+    protected boolean hasContentChanged() {
+        final long startTime = SystemClock.uptimeMillis();
+        final int contactCount = getContactCount();
+        if (contactCount > MAX_CONTACT_COUNT) {
+            // If there are too many contacts then return false. In this rare case it is impossible
+            // to include all of them anyways and the cost of rebuilding the dictionary is too high.
+            // TODO: Sort and check only the MAX_CONTACT_COUNT most recent contacts?
+            return false;
+        }
+        if (contactCount != sContactCountAtLastRebuild) {
+            return true;
+        }
+        // Check all contacts since it's not possible to find out which names have changed.
+        // This is needed because it's possible to receive extraneous onChange events even when no
+        // name has changed.
+        Cursor cursor = mContext.getContentResolver().query(
+                Contacts.CONTENT_URI, PROJECTION, null, null, null);
+        if (cursor != null) {
+            try {
+                if (cursor.moveToFirst()) {
+                    while (!cursor.isAfterLast()) {
+                        String name = cursor.getString(INDEX_NAME);
+                        if (isValidName(name) && !isNameInDictionary(name)) {
+                            if (DEBUG) {
+                                Log.d(TAG, "Contact name missing: " + name + " (runtime = "
+                                        + (SystemClock.uptimeMillis() - startTime) + " ms)");
+                            }
+                            return true;
+                        }
+                        cursor.moveToNext();
+                    }
+                }
+            } finally {
+                cursor.close();
+            }
+        }
+        if (DEBUG) {
+            Log.d(TAG, "No contacts changed. (runtime = " + (SystemClock.uptimeMillis() - startTime)
+                    + " ms)");
+        }
+        return false;
+    }
+
+    private static boolean isValidName(String name) {
+        if (name != null && -1 == name.indexOf('@')) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Checks if the words in a name are in the current binary dictionary.
+     */
+    private boolean isNameInDictionary(String name) {
+        int len = name.codePointCount(0, name.length());
+        String prevWord = null;
+        for (int i = 0; i < len; i++) {
+            if (Character.isLetter(name.codePointAt(i))) {
+                int end = getWordEndPosition(name, len, i);
+                String word = name.substring(i, end);
+                i = end - 1;
+                final int wordLen = word.codePointCount(0, word.length());
+                if (wordLen < MAX_WORD_LENGTH && wordLen > 1) {
+                    if (!TextUtils.isEmpty(prevWord) && mUseFirstLastBigrams) {
+                        if (!super.isValidBigramLocked(prevWord, word)) {
+                            return false;
+                        }
+                    } else {
+                        if (!super.isValidWordLocked(word)) {
+                            return false;
+                        }
+                    }
+                    prevWord = word;
+                }
+            }
+        }
+        return true;
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/ContactsDictionary.java b/java/src/com/android/inputmethod/latin/ContactsDictionary.java
index 8a7dfb8..83bc904 100644
--- a/java/src/com/android/inputmethod/latin/ContactsDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsDictionary.java
@@ -149,7 +149,8 @@
                                 // capitalization of i.
                                 final int wordLen = word.length();
                                 if (wordLen < maxWordLength && wordLen > 1) {
-                                    super.addWord(word, FREQUENCY_FOR_CONTACTS);
+                                    super.addWord(word, null /* shortcut */,
+                                            FREQUENCY_FOR_CONTACTS);
                                     if (!TextUtils.isEmpty(prevWord)) {
                                         super.setBigram(prevWord, word,
                                                 FREQUENCY_FOR_CONTACTS_BIGRAM);
diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java
index a405aa4..1ec678f 100644
--- a/java/src/com/android/inputmethod/latin/Dictionary.java
+++ b/java/src/com/android/inputmethod/latin/Dictionary.java
@@ -24,11 +24,6 @@
  */
 public abstract class Dictionary {
     /**
-     * Whether or not to replicate the typed word in the suggested list, even if it's valid.
-     */
-    protected static final boolean INCLUDE_TYPED_WORD_IF_VALID = false;
-
-    /**
      * The weight to give to a word if it's length is the same as the number of typed characters.
      */
     protected static final int FULL_WORD_SCORE_MULTIPLIER = 2;
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 3d89226..22d8f24 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -96,6 +96,13 @@
     protected abstract void loadDictionaryAsync();
 
     /**
+     * Indicates that the source dictionary content has changed and a rebuild of the binary file is
+     * required. If it returns false, the next reload will only read the current binary dictionary
+     * from file. Note that the shared binary dictionary is locked when this is called.
+     */
+    protected abstract boolean hasContentChanged();
+
+    /**
      * Gets the shared dictionary controller for the given filename.
      */
     private static synchronized DictionaryController getSharedDictionaryController(
@@ -148,8 +155,9 @@
      * the native side.
      */
     public void clearFusionDictionary() {
-        mFusionDictionary = new FusionDictionary(new Node(), new FusionDictionary.DictionaryOptions(
-                new HashMap<String, String>(), false, false));
+        mFusionDictionary = new FusionDictionary(new Node(),
+                new FusionDictionary.DictionaryOptions(new HashMap<String, String>(), false, 
+                        false));
     }
 
     /**
@@ -224,9 +232,7 @@
     protected boolean isValidWordInner(final CharSequence word) {
         if (mLocalDictionaryController.tryLock()) {
             try {
-                if (mBinaryDictionary != null) {
-                    return mBinaryDictionary.isValidWord(word);
-                }
+                return isValidWordLocked(word);
             } finally {
                 mLocalDictionaryController.unlock();
             }
@@ -234,6 +240,32 @@
         return false;
     }
 
+    protected boolean isValidWordLocked(final CharSequence word) {
+        if (mBinaryDictionary == null) return false;
+        return mBinaryDictionary.isValidWord(word);
+    }
+
+    protected boolean isValidBigram(final CharSequence word1, final CharSequence word2) {
+        if (mBinaryDictionary == null) return false;
+        return mBinaryDictionary.isValidBigram(word1, word2);
+    }
+
+    protected boolean isValidBigramInner(final CharSequence word1, final CharSequence word2) {
+        if (mLocalDictionaryController.tryLock()) {
+            try {
+                return isValidBigramLocked(word1, word2);
+            } finally {
+                mLocalDictionaryController.unlock();
+            }
+        }
+        return false;
+    }
+
+    protected boolean isValidBigramLocked(final CharSequence word1, final CharSequence word2) {
+        if (mBinaryDictionary == null) return false;
+        return mBinaryDictionary.isValidBigram(word1, word2);
+    }
+
     /**
      * Load the current binary dictionary from internal storage in a background thread. If no binary
      * dictionary exists, this method will generate one.
@@ -315,12 +347,16 @@
     }
 
     /**
-     * Sets whether or not the dictionary is out of date and requires a reload.
+     * Marks that the dictionary is out of date and requires a reload.
+     *
+     * @param requiresRebuild Indicates that the source dictionary content has changed and a rebuild
+     *        of the binary file is required. If not true, the next reload process will only read
+     *        the current binary dictionary from file.
      */
-    protected void setRequiresReload(final boolean reload) {
-        final long time = reload ? SystemClock.uptimeMillis() : 0;
-        mSharedDictionaryController.mLastUpdateRequestTime = time;
+    protected void setRequiresReload(final boolean requiresRebuild) {
+        final long time = SystemClock.uptimeMillis();
         mLocalDictionaryController.mLastUpdateRequestTime = time;
+        mSharedDictionaryController.mLastUpdateRequestTime = time;
         if (DEBUG) {
             Log.d(TAG, "Reload request: request=" + time + " update="
                     + mSharedDictionaryController.mLastUpdateTime);
@@ -351,21 +387,30 @@
             if (mSharedDictionaryController.isOutOfDate() || !dictionaryFileExists()) {
                 // If the shared dictionary file does not exist or is out of date, the first
                 // instance that acquires the lock will generate a new one.
-                mSharedDictionaryController.mLastUpdateTime = time;
-                mLocalDictionaryController.mLastUpdateTime = time;
-                generateBinaryDictionary();
-                loadBinaryDictionary();
-            } else if (mLocalDictionaryController.isOutOfDate()) {
-                // Otherwise, if only the local dictionary for this instance is out of date, load
-                // the shared dictionary from file.
-                mLocalDictionaryController.mLastUpdateTime = time;
+                if (hasContentChanged()) {
+                    // If the source content has changed, rebuild the binary dictionary.
+                    mSharedDictionaryController.mLastUpdateTime = time;
+                    generateBinaryDictionary();
+                    loadBinaryDictionary();
+                } else {
+                    // If not, the reload request was unnecessary so revert LastUpdateRequestTime
+                    // to LastUpdateTime.
+                    mSharedDictionaryController.mLastUpdateRequestTime =
+                            mSharedDictionaryController.mLastUpdateTime;
+                }
+            } else if (mBinaryDictionary == null || mLocalDictionaryController.mLastUpdateTime
+                    < mSharedDictionaryController.mLastUpdateTime) {
+                // Otherwise, if the local dictionary is older than the shared dictionary, load the
+                // shared dictionary.
                 loadBinaryDictionary();
             }
+            mLocalDictionaryController.mLastUpdateTime = time;
         } finally {
             mSharedDictionaryController.unlock();
         }
     }
 
+    // TODO: cache the file's existence so that we avoid doing a disk access each time.
     private boolean dictionaryFileExists() {
         final File file = new File(mContext.getFilesDir(), mFilename);
         return file.exists();
diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
index fe21ebe..7a740b3 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
@@ -22,6 +22,7 @@
 import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.keyboard.ProximityInfo;
 
+import java.util.ArrayList;
 import java.util.LinkedList;
 
 /**
@@ -53,6 +54,8 @@
         boolean mTerminal;
         Node mParent;
         NodeArray mChildren;
+        ArrayList<char[]> mShortcutTargets;
+        boolean mShortcutOnly;
         LinkedList<NextWord> mNGrams; // Supports ngram
     }
 
@@ -150,15 +153,15 @@
         return BinaryDictionary.MAX_WORD_LENGTH;
     }
 
-    public void addWord(String word, int frequency) {
+    public void addWord(final String word, final String shortcutTarget, final int frequency) {
         if (word.length() >= BinaryDictionary.MAX_WORD_LENGTH) {
             return;
         }
-        addWordRec(mRoots, word, 0, frequency, null);
+        addWordRec(mRoots, word, 0, shortcutTarget, frequency, null);
     }
 
     private void addWordRec(NodeArray children, final String word, final int depth,
-            final int frequency, Node parentNode) {
+            final String shortcutTarget, final int frequency, Node parentNode) {
         final int wordLength = word.length();
         if (wordLength <= depth) return;
         final char c = word.charAt(depth);
@@ -172,15 +175,25 @@
                 break;
             }
         }
+        final boolean isShortcutOnly = (null != shortcutTarget);
         if (childNode == null) {
             childNode = new Node();
             childNode.mCode = c;
             childNode.mParent = parentNode;
+            childNode.mShortcutOnly = isShortcutOnly;
             children.add(childNode);
         }
         if (wordLength == depth + 1) {
             // Terminate this word
             childNode.mTerminal = true;
+            if (isShortcutOnly) {
+                if (null == childNode.mShortcutTargets) {
+                    childNode.mShortcutTargets = new ArrayList<char[]>();
+                }
+                childNode.mShortcutTargets.add(shortcutTarget.toCharArray());
+            } else {
+                childNode.mShortcutOnly = false;
+            }
             childNode.mFrequency = Math.max(frequency, childNode.mFrequency);
             if (childNode.mFrequency > 255) childNode.mFrequency = 255;
             return;
@@ -188,7 +201,7 @@
         if (childNode.mChildren == null) {
             childNode.mChildren = new NodeArray();
         }
-        addWordRec(childNode.mChildren, word, depth + 1, frequency, childNode);
+        addWordRec(childNode.mChildren, word, depth + 1, shortcutTarget, frequency, childNode);
     }
 
     @Override
@@ -239,7 +252,13 @@
             if (mRequiresReload) startDictionaryLoadingTaskLocked();
             if (mUpdatingDictionary) return false;
         }
-        return getWordFrequency(word) > -1;
+        final Node node = searchNode(mRoots, word, 0, word.length());
+        // If node is null, we didn't find the word, so it's not valid.
+        // If node.mShortcutOnly is true, then it exists as a shortcut but not as a word,
+        // so that means it's not a valid word.
+        // If node.mShortcutOnly is false, then it exists as a word (it may also exist as
+        // a shortcut, but this does not matter), so it's a valid word.
+        return (node == null) ? false : !node.mShortcutOnly;
     }
 
     /**
@@ -247,7 +266,7 @@
      */
     protected int getWordFrequency(CharSequence word) {
         // Case-sensitive search
-        Node node = searchNode(mRoots, word, 0, word.length());
+        final Node node = searchNode(mRoots, word, 0, word.length());
         return (node == null) ? -1 : node.mFrequency;
     }
 
@@ -262,6 +281,35 @@
     }
 
     /**
+     * Helper method to add a word and its shortcuts.
+     *
+     * @param node the terminal node
+     * @param word the word to insert, as an array of code points
+     * @param depth the depth of the node in the tree
+     * @param finalFreq the frequency for this word
+     * @return whether there is still space for more words. {@see Dictionary.WordCallback#addWord}.
+     */
+    private boolean addWordAndShortcutsFromNode(final Node node, final char[] word, final int depth,
+            final int finalFreq, final WordCallback callback) {
+        if (finalFreq > 0 && !node.mShortcutOnly) {
+            if (!callback.addWord(word, 0, depth + 1, finalFreq, mDicTypeId, Dictionary.UNIGRAM)) {
+                return false;
+            }
+        }
+        if (null != node.mShortcutTargets) {
+            final int length = node.mShortcutTargets.size();
+            for (int shortcutIndex = 0; shortcutIndex < length; ++shortcutIndex) {
+                final char[] shortcut = node.mShortcutTargets.get(shortcutIndex);
+                if (!callback.addWord(shortcut, 0, shortcut.length, finalFreq, mDicTypeId,
+                        Dictionary.UNIGRAM)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
      * Recursively traverse the tree for words that match the input. Input consists of
      * a list of arrays. Each item in the list is one input character position. An input
      * character is actually an array of multiple possible candidates. This function is not
@@ -313,8 +361,8 @@
                     } else {
                         finalFreq = computeSkippedWordFinalFreq(freq, snr, mInputLength);
                     }
-                    if (!callback.addWord(word, 0, depth + 1, finalFreq, mDicTypeId,
-                            Dictionary.UNIGRAM)) {
+                    if (!addWordAndShortcutsFromNode(node, word, depth, finalFreq, callback)) {
+                        // No space left in the queue, bail out
                         return;
                     }
                 }
@@ -344,18 +392,18 @@
 
                         if (codeSize == inputIndex + 1) {
                             if (terminal) {
-                                if (INCLUDE_TYPED_WORD_IF_VALID
-                                        || !same(word, depth + 1, codes.getTypedWord())) {
-                                    final int finalFreq;
-                                    if (skipPos < 0) {
-                                        finalFreq = freq * snr * addedAttenuation
-                                                * FULL_WORD_SCORE_MULTIPLIER;
-                                    } else {
-                                        finalFreq = computeSkippedWordFinalFreq(freq,
-                                                snr * addedAttenuation, mInputLength);
-                                    }
-                                    callback.addWord(word, 0, depth + 1, finalFreq, mDicTypeId,
-                                            Dictionary.UNIGRAM);
+                                final int finalFreq;
+                                if (skipPos < 0) {
+                                    finalFreq = freq * snr * addedAttenuation
+                                            * FULL_WORD_SCORE_MULTIPLIER;
+                                } else {
+                                    finalFreq = computeSkippedWordFinalFreq(freq,
+                                            snr * addedAttenuation, mInputLength);
+                                }
+                                if (!addWordAndShortcutsFromNode(node, word, depth, finalFreq,
+                                        callback)) {
+                                    // No space left in the queue, bail out
+                                    return;
                                 }
                             }
                             if (children != null) {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 011b512..b59e939 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -877,7 +877,8 @@
                     false /* hasAutoCorrectionCandidate */,
                     false /* allowsToBeAutoCorrected */,
                     false /* isPunctuationSuggestions */,
-                    false /* isObsoleteSuggestions */);
+                    false /* isObsoleteSuggestions */,
+                    false /* isPrediction */);
             // When in fullscreen mode, show completions generated by the application
             final boolean isAutoCorrection = false;
             setSuggestions(suggestedWords, isAutoCorrection);
@@ -1120,7 +1121,7 @@
 
     @Override
     public boolean addWordToDictionary(String word) {
-        mUserDictionary.addWord(word, 128);
+        mUserDictionary.addWordToUserDictionary(word, 128);
         // Suggestion strip should be updated after the operation of adding word to the
         // user dictionary
         mHandler.postUpdateSuggestions();
@@ -1772,7 +1773,8 @@
                             false /* hasAutoCorrectionCandidate */,
                             false /* allowsToBeAutoCorrected */,
                             false /* isPunctuationSuggestions */,
-                            true /* isObsoleteSuggestions */);
+                            true /* isObsoleteSuggestions */,
+                            false /* isPrediction */);
             showSuggestions(obsoleteSuggestedWords, typedWord);
         }
     }
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index 5f9e1bc..55b896f 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -166,7 +166,8 @@
                 false /* hasAutoCorrectionCandidate */,
                 false /* allowsToBeAutoCorrected */,
                 true /* isPunctuationSuggestions */,
-                false /* isObsoleteSuggestions */);
+                false /* isObsoleteSuggestions */,
+                false /* isPrediction */);
     }
 
     private static String createWordSeparators(final String weakSpaceStrippers,
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 112bde6..845df81 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -253,13 +253,12 @@
         SuggestedWordInfo.removeDups(mSuggestions);
 
         return new SuggestedWords(mSuggestions,
-                // TODO: Just assuming the suggestions that came from the bigram prediction are
-                // valid now. Need to assign a correct value for typedWordValid.
-                true /* typedWordValid */,
+                false /* typedWordValid */,
                 false /* hasAutoCorrectionCandidate */,
                 false /* allowsToBeAutoCorrected */,
                 false /* isPunctuationSuggestions */,
-                false /* isObsoleteSuggestions */);
+                false /* isObsoleteSuggestions */,
+                true /* isPrediction */);
     }
 
     // TODO: cleanup dictionaries looking up and suggestions building with SuggestedWords.Builder
@@ -396,7 +395,8 @@
                 autoCorrectionAvailable /* hasAutoCorrectionCandidate */,
                 allowsToBeAutoCorrected /* allowsToBeAutoCorrected */,
                 false /* isPunctuationSuggestions */,
-                false /* isObsoleteSuggestions */);
+                false /* isObsoleteSuggestions */,
+                false /* isPrediction */);
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index 91110d8..497fd3b 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -25,13 +25,14 @@
 
 public class SuggestedWords {
     public static final SuggestedWords EMPTY = new SuggestedWords(
-            new ArrayList<SuggestedWordInfo>(0), false, false, false, false, false);
+            new ArrayList<SuggestedWordInfo>(0), false, false, false, false, false, false);
 
     public final boolean mTypedWordValid;
     public final boolean mHasAutoCorrectionCandidate;
     public final boolean mIsPunctuationSuggestions;
     public final boolean mAllowsToBeAutoCorrected;
     public final boolean mIsObsoleteSuggestions;
+    public final boolean mIsPrediction;
     private final ArrayList<SuggestedWordInfo> mSuggestedWordInfoList;
 
     public SuggestedWords(final ArrayList<SuggestedWordInfo> suggestedWordInfoList,
@@ -39,13 +40,15 @@
             final boolean hasAutoCorrectionCandidate,
             final boolean allowsToBeAutoCorrected,
             final boolean isPunctuationSuggestions,
-            final boolean isObsoleteSuggestions) {
+            final boolean isObsoleteSuggestions,
+            final boolean isPrediction) {
         mSuggestedWordInfoList = suggestedWordInfoList;
         mTypedWordValid = typedWordValid;
         mHasAutoCorrectionCandidate = hasAutoCorrectionCandidate;
         mAllowsToBeAutoCorrected = allowsToBeAutoCorrected;
         mIsPunctuationSuggestions = isPunctuationSuggestions;
         mIsObsoleteSuggestions = isObsoleteSuggestions;
+        mIsPrediction = isPrediction;
     }
 
     public int size() {
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java
index 50e8b24..b78be89 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java
@@ -42,6 +42,6 @@
     @Override
     public synchronized boolean isValidWord(CharSequence word) {
         blockingReloadDictionaryIfRequired();
-        return getWordFrequency(word) > -1;
+        return super.isValidWord(word);
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/UserDictionary.java b/java/src/com/android/inputmethod/latin/UserDictionary.java
index 6beeaac..218bac7 100644
--- a/java/src/com/android/inputmethod/latin/UserDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserDictionary.java
@@ -31,8 +31,11 @@
 
 public class UserDictionary extends ExpandableDictionary {
 
+    // TODO: use Words.SHORTCUT when it's public in the SDK
+    final static String SHORTCUT = "shortcut";
     private static final String[] PROJECTION_QUERY = {
         Words.WORD,
+        SHORTCUT,
         Words.FREQUENCY,
     };
 
@@ -149,15 +152,18 @@
     }
 
     /**
-     * Adds a word to the dictionary and makes it persistent.
+     * Adds a word to the user dictionary and makes it persistent.
+     *
+     * This will call upon the system interface to do the actual work through the intent
+     * readied by the system to this effect.
+     *
      * @param word the word to add. If the word is capitalized, then the dictionary will
      * recognize it as a capitalized word when searched.
      * @param frequency the frequency of occurrence of the word. A frequency of 255 is considered
      * the highest.
      * @TODO use a higher or float range for frequency
      */
-    @Override
-    public synchronized void addWord(final String word, final int frequency) {
+    public synchronized void addWordToUserDictionary(final String word, final int frequency) {
         // Force load the dictionary here synchronously
         if (getRequiresReload()) loadDictionaryAsync();
         // TODO: do something for the UI. With the following, any sufficiently long word will
@@ -191,14 +197,19 @@
         final int maxWordLength = getMaxWordLength();
         if (cursor.moveToFirst()) {
             final int indexWord = cursor.getColumnIndex(Words.WORD);
+            final int indexShortcut = cursor.getColumnIndex(SHORTCUT);
             final int indexFrequency = cursor.getColumnIndex(Words.FREQUENCY);
             while (!cursor.isAfterLast()) {
                 String word = cursor.getString(indexWord);
+                String shortcut = cursor.getString(indexShortcut);
                 int frequency = cursor.getInt(indexFrequency);
                 // Safeguard against adding really long words. Stack may overflow due
                 // to recursion
                 if (word.length() < maxWordLength) {
-                    super.addWord(word, frequency);
+                    super.addWord(word, null, frequency);
+                }
+                if (null != shortcut && shortcut.length() < maxWordLength) {
+                    super.addWord(shortcut, word, frequency);
                 }
                 cursor.moveToNext();
             }
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
index 9191aa9..e13602e 100644
--- a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
@@ -176,7 +176,7 @@
      * The second word may not be null (a NullPointerException would be thrown).
      */
     public int addToUserHistory(final String word1, String word2) {
-        super.addWord(word2, FREQUENCY_FOR_TYPED);
+        super.addWord(word2, null /* shortcut */, FREQUENCY_FOR_TYPED);
         // Do not insert a word as a bigram of itself
         if (word2.equals(word1)) {
             return 0;
@@ -246,7 +246,7 @@
                     // Safeguard against adding really long words. Stack may overflow due
                     // to recursive lookup
                     if (null == word1) {
-                        super.addWord(word2, frequency);
+                        super.addWord(word2, null /* shortcut */, frequency);
                     } else if (word1.length() < BinaryDictionary.MAX_WORD_LENGTH
                             && word2.length() < BinaryDictionary.MAX_WORD_LENGTH) {
                         super.setBigram(word1, word2, frequency);
diff --git a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java
index bb3ba86..a0de2f9 100644
--- a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java
+++ b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java
@@ -66,7 +66,7 @@
                 if (before != null && after != null) {
                     mWhitelistWords.put(
                             before.toLowerCase(), new Pair<Integer, String>(score, after));
-                    addWord(after, score);
+                    addWord(after, null /* shortcut */, score);
                 }
             }
         } catch (NumberFormatException e) {
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
index 3c818cc..563f8a9 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
@@ -40,6 +40,8 @@
  */
 public class BinaryDictInputOutput {
 
+    final static boolean DBG = MakedictLog.DBG;
+
     /* Node layout is as follows:
      *   | addressType                         xx     : mask with MASK_GROUP_ADDRESS_TYPE
      *                                 2 bits, 00 = no children : FLAG_GROUP_ADDRESS_TYPE_NOADDRESS
@@ -489,10 +491,17 @@
         // Merging tails can only be done if there are no attributes. Searching for attributes
         // in LatinIME code depends on a total breadth-first ordering, which merging tails
         // breaks. If there are no attributes, it should be fine (and reduce the file size)
-        // to merge tails, and the following step would be necessary.
-        // If eventually the code runs on Android, searching through the whole array each time
-        // may be a performance concern.
-        list.remove(node);
+        // to merge tails, and removing the node from the list would be necessary. However,
+        // we don't merge tails because breaking the breadth-first ordering would result in
+        // extreme overhead at bigram lookup time (it would make the search function O(n) instead
+        // of the current O(log(n)), where n=number of nodes in the dictionary which is pretty
+        // high).
+        // If no nodes are ever merged, we can't have the same node twice in the list, hence
+        // searching for duplicates in unnecessary. It is also very performance consuming,
+        // since `list' is an ArrayList so it's an O(n) operation that runs on all nodes, making
+        // this simple list.remove operation O(n*n) overall. On Android this overhead is very
+        // high.
+        // For future reference, the code to remove duplicate is a simple : list.remove(node);
         list.add(node);
         final ArrayList<CharGroup> branches = node.mData;
         final int nodeSize = branches.size();
@@ -708,13 +717,13 @@
              }
         }
         if (null != group.mShortcutTargets) {
-            if (0 == group.mShortcutTargets.size()) {
+            if (DBG && 0 == group.mShortcutTargets.size()) {
                 throw new RuntimeException("0-sized shortcut list must be null");
             }
             flags |= FLAG_HAS_SHORTCUT_TARGETS;
         }
         if (null != group.mBigrams) {
-            if (0 == group.mBigrams.size()) {
+            if (DBG && 0 == group.mBigrams.size()) {
                 throw new RuntimeException("0-sized bigram list must be null");
             }
             flags |= FLAG_HAS_BIGRAMS;
@@ -756,14 +765,39 @@
             bigramFrequency = unigramFrequency;
         }
         // We compute the difference between 255 (which means probability = 1) and the
-        // unigram score. We split this into discrete 16 steps, and this is the value
-        // we store into the 4 bits of the bigrams frequency.
-        final float bigramRatio = (float)(bigramFrequency - unigramFrequency)
-                / (MAX_TERMINAL_FREQUENCY - unigramFrequency);
-        // TODO: if the bigram freq is very close to the unigram frequency, we don't want
-        // to include the bigram in the binary dictionary at all.
-        final int discretizedFrequency = Math.round(bigramRatio * MAX_BIGRAM_FREQUENCY);
-        bigramFlags += discretizedFrequency & FLAG_ATTRIBUTE_FREQUENCY;
+        // unigram score. We split this into a number of discrete steps.
+        // Now, the steps are numbered 0~15; 0 represents an increase of 1 step while 15
+        // represents an increase of 16 steps: a value of 15 will be interpreted as the median
+        // value of the 16th step. In all justice, if the bigram frequency is low enough to be
+        // rounded below the first step (which means it is less than half a step higher than the
+        // unigram frequency) then the unigram frequency itself is the best approximation of the
+        // bigram freq that we could possibly supply, hence we should *not* include this bigram
+        // in the file at all.
+        // until this is done, we'll write 0 and slightly overestimate this case.
+        // In other words, 0 means "between 0.5 step and 1.5 step", 1 means "between 1.5 step
+        // and 2.5 steps", and 15 means "between 15.5 steps and 16.5 steps". So we want to
+        // divide our range [unigramFreq..MAX_TERMINAL_FREQUENCY] in 16.5 steps to get the
+        // step size. Then we compute the start of the first step (the one where value 0 starts)
+        // by adding half-a-step to the unigramFrequency. From there, we compute the integer
+        // number of steps to the bigramFrequency. One last thing: we want our steps to include
+        // their lower bound and exclude their higher bound so we need to have the first step
+        // start at exactly 1 unit higher than floor(unigramFreq + half a step).
+        // Note : to reconstruct the score, the dictionary reader will need to divide
+        // MAX_TERMINAL_FREQUENCY - unigramFreq by 16.5 likewise, and add
+        // (discretizedFrequency + 0.5) times this value to get the median value of the step,
+        // which is the best approximation. This is how we get the most precise result with
+        // only four bits.
+        final double stepSize =
+                (double)(MAX_TERMINAL_FREQUENCY - unigramFrequency) / (1.5 + MAX_BIGRAM_FREQUENCY);
+        final double firstStepStart = 1 + unigramFrequency + (stepSize / 2.0);
+        final int discretizedFrequency = (int)((bigramFrequency - firstStepStart) / stepSize);
+        // If the bigram freq is less than half-a-step higher than the unigram freq, we get -1
+        // here. The best approximation would be the unigram freq itself, so we should not
+        // include this bigram in the dictionary. For now, register as 0, and live with the
+        // small over-estimation that we get in this case. TODO: actually remove this bigram
+        // if discretizedFrequency < 0.
+        final int finalBigramFrequency = discretizedFrequency > 0 ? discretizedFrequency : 0;
+        bigramFlags += finalBigramFrequency & FLAG_ATTRIBUTE_FREQUENCY;
         return bigramFlags;
     }
 
@@ -823,7 +857,7 @@
                     + index + " <> " + group.mCachedAddress);
             groupAddress += GROUP_FLAGS_SIZE + getGroupCharactersSize(group);
             // Sanity checks.
-            if (group.mFrequency > MAX_TERMINAL_FREQUENCY) {
+            if (DBG && group.mFrequency > MAX_TERMINAL_FREQUENCY) {
                 throw new RuntimeException("A node has a frequency > " + MAX_TERMINAL_FREQUENCY
                         + " : " + group.mFrequency);
             }
@@ -1030,7 +1064,7 @@
         MakedictLog.i("Computing addresses...");
         computeAddresses(dict, flatNodes);
         MakedictLog.i("Checking array...");
-        checkFlatNodeArray(flatNodes);
+        if (DBG) checkFlatNodeArray(flatNodes);
 
         // Create a buffer that matches the final dictionary size.
         final Node lastNode = flatNodes.get(flatNodes.size() - 1);
@@ -1044,7 +1078,7 @@
             dataEndOffset = writePlacedNode(dict, buffer, n);
         }
 
-        showStatistics(flatNodes);
+        if (DBG) showStatistics(flatNodes);
 
         destination.write(buffer, 0, dataEndOffset);
 
diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
index b08702e..c467ef7 100644
--- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
+++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
@@ -28,6 +28,8 @@
  */
 public class FusionDictionary implements Iterable<Word> {
 
+    private static final boolean DBG = MakedictLog.DBG;
+
     /**
      * A node of the dictionary, containing several CharGroups.
      *
@@ -159,6 +161,7 @@
          * shortcut list.
          */
         public WeightedString getShortcut(final String word) {
+            // TODO: Don't do a linear search
             if (mShortcutTargets != null) {
                 final int size = mShortcutTargets.size();
                 for (int i = 0; i < size; ++i) {
@@ -176,6 +179,7 @@
          * Returns null if the word is not in the bigrams list.
          */
         public WeightedString getBigram(final String word) {
+            // TODO: Don't do a linear search
             if (mBigrams != null) {
                 final int size = mBigrams.size();
                 for (int i = 0; i < size; ++i) {
@@ -265,31 +269,21 @@
     /**
      * Helper method to convert a String to an int array.
      */
-    static private int[] getCodePoints(String word) {
-        final int wordLength = word.length();
-        int[] array = new int[word.codePointCount(0, wordLength)];
-        for (int i = 0; i < wordLength; i = word.offsetByCodePoints(i, 1)) {
-            array[i] = word.codePointAt(i);
+    static private int[] getCodePoints(final String word) {
+        // TODO: this is a copy-paste of the contents of StringUtils.toCodePointArray,
+        // which is not visible from the makedict package. Factor this code.
+        final char[] characters = word.toCharArray();
+        final int length = characters.length;
+        final int[] codePoints = new int[Character.codePointCount(characters, 0, length)];
+        int codePoint = Character.codePointAt(characters, 0);
+        int dsti = 0;
+        for (int srci = Character.charCount(codePoint);
+                srci < length; srci += Character.charCount(codePoint), ++dsti) {
+            codePoints[dsti] = codePoint;
+            codePoint = Character.codePointAt(characters, srci);
         }
-        return array;
-    }
-
-    /**
-     * Helper method to add all words in a list as 0-frequency entries
-     *
-     * These words are added when shortcuts targets or bigrams are not found in the dictionary
-     * yet. The same words may be added later with an actual frequency - this is handled by
-     * the private version of add().
-     */
-    private void addNeutralWords(final ArrayList<WeightedString> words) {
-        if (null != words) {
-            for (WeightedString word : words) {
-                final CharGroup t = findWordInTree(mRoot, word.mWord);
-                if (null == t) {
-                    add(getCodePoints(word.mWord), 0, null);
-                }
-            }
-        }
+        codePoints[dsti] = codePoint;
+        return codePoints;
     }
 
     /**
@@ -339,7 +333,6 @@
         if (charGroup != null) {
             final CharGroup charGroup2 = findWordInTree(mRoot, word2);
             if (charGroup2 == null) {
-                // TODO: refactor with the identical code in addNeutralWords
                 add(getCodePoints(word2), 0, null);
             }
             charGroup.addBigram(word2, frequency);
@@ -386,7 +379,7 @@
                     Arrays.copyOfRange(word, charIndex, word.length),
                     shortcutTargets, null /* bigrams */, frequency);
             currentNode.mData.add(insertionIndex, newGroup);
-            checkStack(currentNode);
+            if (DBG) checkStack(currentNode);
         } else {
             // There is a word with a common prefix.
             if (differentCharIndex == currentGroup.mChars.length) {
@@ -437,7 +430,7 @@
                     }
                     currentNode.mData.set(nodeIndex, newParent);
                 }
-                checkStack(currentNode);
+                if (DBG) checkStack(currentNode);
             }
         }
     }
@@ -514,21 +507,21 @@
      */
     public static CharGroup findWordInTree(Node node, final String s) {
         int index = 0;
-        final StringBuilder checker = new StringBuilder();
+        final StringBuilder checker = DBG ? new StringBuilder() : null;
 
         CharGroup currentGroup;
         do {
             int indexOfGroup = findIndexOfChar(node, s.codePointAt(index));
             if (CHARACTER_NOT_FOUND == indexOfGroup) return null;
             currentGroup = node.mData.get(indexOfGroup);
-            checker.append(new String(currentGroup.mChars, 0, currentGroup.mChars.length));
+            if (DBG) checker.append(new String(currentGroup.mChars, 0, currentGroup.mChars.length));
             index += currentGroup.mChars.length;
             if (index < s.length()) {
                 node = currentGroup.mChildren;
             }
         } while (null != node && index < s.length());
 
-        if (!s.equals(checker.toString())) return null;
+        if (DBG && !s.equals(checker.toString())) return null;
         return currentGroup;
     }
 
diff --git a/java/src/com/android/inputmethod/latin/makedict/MakedictLog.java b/java/src/com/android/inputmethod/latin/makedict/MakedictLog.java
index 1281c7e..3f0cd07 100644
--- a/java/src/com/android/inputmethod/latin/makedict/MakedictLog.java
+++ b/java/src/com/android/inputmethod/latin/makedict/MakedictLog.java
@@ -22,7 +22,7 @@
  * Wrapper to redirect log events to the right output medium.
  */
 public class MakedictLog {
-    private static final boolean DBG = false;
+    public static final boolean DBG = false;
     private static final String TAG = MakedictLog.class.getSimpleName();
 
     public static void d(String message) {
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index de9dbf9..b8f4ec7 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -182,6 +182,20 @@
     return result;
 }
 
+static jboolean latinime_BinaryDictionary_isValidBigram(JNIEnv *env, jobject object, jlong dict,
+        jintArray wordArray1, jintArray wordArray2) {
+    Dictionary *dictionary = (Dictionary*)dict;
+    if (!dictionary) return (jboolean) false;
+    jint *word1 = env->GetIntArrayElements(wordArray1, 0);
+    jint *word2 = env->GetIntArrayElements(wordArray2, 0);
+    jsize length1 = word1 ? env->GetArrayLength(wordArray1) : 0;
+    jsize length2 = word2 ? env->GetArrayLength(wordArray2) : 0;
+    jboolean result = dictionary->isValidBigram(word1, length1, word2, length2);
+    env->ReleaseIntArrayElements(wordArray2, word2, JNI_ABORT);
+    env->ReleaseIntArrayElements(wordArray1, word1, JNI_ABORT);
+    return result;
+}
+
 static jdouble latinime_BinaryDictionary_calcNormalizedScore(JNIEnv *env, jobject object,
         jcharArray before, jint beforeLength, jcharArray after, jint afterLength, jint score) {
     jchar *beforeChars = env->GetCharArrayElements(before, 0);
@@ -239,6 +253,7 @@
     {"getSuggestionsNative", "(JJ[I[I[II[IZ[C[I)I",
             (void*)latinime_BinaryDictionary_getSuggestions},
     {"isValidWordNative", "(J[II)Z", (void*)latinime_BinaryDictionary_isValidWord},
+    {"isValidBigramNative", "(J[I[I)Z", (void*)latinime_BinaryDictionary_isValidBigram},
     {"getBigramsNative", "(J[II[II[C[III)I", (void*)latinime_BinaryDictionary_getBigrams},
     {"calcNormalizedScoreNative", "([CI[CII)D",
             (void*)latinime_BinaryDictionary_calcNormalizedScore},
diff --git a/native/jni/src/bigram_dictionary.cpp b/native/jni/src/bigram_dictionary.cpp
index 0703108..7ed4dc4 100644
--- a/native/jni/src/bigram_dictionary.cpp
+++ b/native/jni/src/bigram_dictionary.cpp
@@ -128,7 +128,7 @@
                 ++bigramCount;
             }
         }
-    } while (0 != (UnigramDictionary::FLAG_ATTRIBUTE_HAS_NEXT & bigramFlags));
+    } while (UnigramDictionary::FLAG_ATTRIBUTE_HAS_NEXT & bigramFlags);
     return bigramCount;
 }
 
@@ -189,5 +189,25 @@
     return false;
 }
 
+bool BigramDictionary::isValidBigram(const int32_t *word1, int length1, const int32_t *word2,
+        int length2) {
+    const uint8_t* const root = DICT;
+    int pos = getBigramListPositionForWord(word1, length1);
+    // getBigramListPositionForWord returns 0 if this word isn't in the dictionary or has no bigrams
+    if (0 == pos) return false;
+    int nextWordPos = BinaryFormat::getTerminalPosition(root, word2, length2);
+    if (NOT_VALID_WORD == nextWordPos) return false;
+    int bigramFlags;
+    do {
+        bigramFlags = BinaryFormat::getFlagsAndForwardPointer(root, &pos);
+        const int bigramPos = BinaryFormat::getAttributeAddressAndForwardPointer(root, bigramFlags,
+                &pos);
+        if (bigramPos == nextWordPos) {
+            return true;
+        }
+    } while (UnigramDictionary::FLAG_ATTRIBUTE_HAS_NEXT & bigramFlags);
+    return false;
+}
+
 // TODO: Move functions related to bigram to here
 } // namespace latinime
diff --git a/native/jni/src/bigram_dictionary.h b/native/jni/src/bigram_dictionary.h
index 7328d58..b8763a5 100644
--- a/native/jni/src/bigram_dictionary.h
+++ b/native/jni/src/bigram_dictionary.h
@@ -33,6 +33,7 @@
     int getBigramListPositionForWord(const int32_t *prevWord, const int prevWordLength);
     void fillBigramAddressToFrequencyMapAndFilter(const int32_t *prevWord, const int prevWordLength,
             std::map<int, int> *map, uint8_t *filter);
+    bool isValidBigram(const int32_t *word1, int length1, const int32_t *word2, int length2);
     ~BigramDictionary();
  private:
     bool addWordBigram(unsigned short *word, int length, int frequency);
diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp
index 376e9a1..a1f8129 100644
--- a/native/jni/src/correction.cpp
+++ b/native/jni/src/correction.cpp
@@ -344,8 +344,10 @@
                 mDistances[mOutputIndex] =
                         mProximityInfo->getNormalizedSquaredDistance(mInputIndex, proximityIndex);
             }
-            incrementInputIndex();
-            incremented = true;
+            if (!isQuote(c)) {
+                incrementInputIndex();
+                incremented = true;
+            }
         }
         return processSkipChar(c, isTerminal, incremented);
     }
@@ -710,7 +712,7 @@
         ed = max(0, ed - quoteDiffCount);
         adjustedProximityMatchedCount = min(max(0, ed - (outputLength - inputLength)),
                 proximityMatchedCount);
-        if (transposedCount < 1) {
+        if (transposedCount <= 0) {
             if (ed == 1 && (inputLength == outputLength - 1 || inputLength == outputLength + 1)) {
                 // Promote a word with just one skipped or excessive char
                 if (sameLength) {
diff --git a/native/jni/src/dictionary.cpp b/native/jni/src/dictionary.cpp
index 9dc2072..8ea7c49 100644
--- a/native/jni/src/dictionary.cpp
+++ b/native/jni/src/dictionary.cpp
@@ -58,4 +58,9 @@
     return mUnigramDictionary->isValidWord(word, length);
 }
 
+bool Dictionary::isValidBigram(const int32_t *word1, int length1, const int32_t *word2,
+        int length2) {
+    return mBigramDictionary->isValidBigram(word1, length1, word2, length2);
+}
+
 } // namespace latinime
diff --git a/native/jni/src/dictionary.h b/native/jni/src/dictionary.h
index bce86d1..87891ee 100644
--- a/native/jni/src/dictionary.h
+++ b/native/jni/src/dictionary.h
@@ -53,6 +53,7 @@
     }
 
     bool isValidWord(const int32_t *word, int length);
+    bool isValidBigram(const int32_t *word1, int length1, const int32_t *word2, int length2);
     void *getDict() { return (void *)mDict; }
     int getDictSize() { return mDictSize; }
     int getMmapFd() { return mMmapFd; }
diff --git a/tools/makedict/src/com/android/inputmethod/latin/makedict/MakedictLog.java b/tools/makedict/src/com/android/inputmethod/latin/makedict/MakedictLog.java
index 1ab9f42..7eccff2 100644
--- a/tools/makedict/src/com/android/inputmethod/latin/makedict/MakedictLog.java
+++ b/tools/makedict/src/com/android/inputmethod/latin/makedict/MakedictLog.java
@@ -20,6 +20,8 @@
  * Wrapper to redirect log events to the right output medium.
  */
 public class MakedictLog {
+    public static final boolean DBG = true;
+
     private static void print(String message) {
         System.out.println(message);
     }