Auto mini keyboard layout

Bug: 4280617
Change-Id: I34c344cbf350fe125589aa14ad69e4bd1f4e6f66
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index 32fb5bf..5aabcb8 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -63,7 +63,7 @@
     <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
     <string name="config_default_keyboard_theme_id" translatable="false">4</string>
     <string name="config_text_size_of_language_on_spacebar" translatable="false">small</string>
-    <integer name="config_max_popup_keyboard_column">10</integer>
+    <integer name="config_max_popup_keyboard_column">5</integer>
     <!-- Whether or not auto-correction should be enabled by default -->
     <bool name="enable_autocorrect">true</bool>
     <string-array name="auto_correction_threshold_values" translatable="false">
diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
index 3b923e1..bf0fb9a 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
@@ -17,7 +17,6 @@
 package com.android.inputmethod.keyboard;
 
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
 
 public abstract class KeyDetector {
@@ -110,31 +109,4 @@
      * @return The nearest key index
      */
     abstract public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes);
-
-    /**
-     * Compute the most common key width in order to use it as proximity key detection threshold.
-     *
-     * @param keyboard The keyboard to compute the most common key width
-     * @return The most common key width in the keyboard
-     */
-    public static int getMostCommonKeyWidth(final Keyboard keyboard) {
-        if (keyboard == null) return 0;
-        final List<Key> keys = keyboard.getKeys();
-        if (keys == null || keys.size() == 0) return 0;
-        final HashMap<Integer, Integer> histogram = new HashMap<Integer, Integer>();
-        int maxCount = 0;
-        int mostCommonWidth = 0;
-        for (final Key key : keys) {
-            final Integer width = key.mWidth + key.mGap;
-            Integer count = histogram.get(width);
-            if (count == null)
-                count = 0;
-            histogram.put(width, ++count);
-            if (count > maxCount) {
-                maxCount = count;
-                mostCommonWidth = width;
-            }
-        }
-        return mostCommonWidth + keyboard.getHorizontalGap();
-    }
 }
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index f720334..9b8d75e 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -405,6 +405,29 @@
         return EMPTY_INT_ARRAY;
     }
 
+    /**
+     * Compute the most common key width in order to use it as proximity key detection threshold.
+     *
+     * @return The most common key width in the keyboard
+     */
+    public int getMostCommonKeyWidth() {
+        final HashMap<Integer, Integer> histogram = new HashMap<Integer, Integer>();
+        int maxCount = 0;
+        int mostCommonWidth = 0;
+        for (final Key key : mKeys) {
+            final Integer width = key.mWidth + key.mGap;
+            Integer count = histogram.get(width);
+            if (count == null)
+                count = 0;
+            histogram.put(width, ++count);
+            if (count > maxCount) {
+                maxCount = count;
+                mostCommonWidth = width;
+            }
+        }
+        return mostCommonWidth;
+    }
+
     private void loadKeyboard(Context context, int xmlLayoutResId) {
         try {
             KeyboardParser parser = new KeyboardParser(this, context.getResources());
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index dee1913..1e19a8a 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -501,7 +501,7 @@
         requestLayout();
         mKeyboardChanged = true;
         invalidateAllKeys();
-        mKeyDetector.setProximityThreshold(KeyDetector.getMostCommonKeyWidth(keyboard));
+        mKeyDetector.setProximityThreshold(keyboard.getMostCommonKeyWidth());
         mMiniKeyboardCache.clear();
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboardBuilder.java
index 53dab94..e540fa1 100644
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboardBuilder.java
@@ -34,7 +34,7 @@
     /* package */ static class MiniKeyboardLayoutParams {
         public final int mKeyWidth;
         public final int mRowHeight;
-        /* package */ final boolean mTopRowNeedsCentering;
+        /* package */ final int mTopRowAdjustment;
         public final int mNumRows;
         public final int mNumColumns;
         public final int mLeftKeys;
@@ -55,29 +55,52 @@
             if (parentKeyboardWidth / keyWidth < maxColumns)
                 throw new IllegalArgumentException("Keyboard is too small to hold mini keyboard: "
                         + parentKeyboardWidth + " " + keyWidth + " " + maxColumns);
-            final int numRows = (numKeys + maxColumns - 1) / maxColumns;
             mKeyWidth = keyWidth;
             mRowHeight = rowHeight;
-            mNumRows = numRows;
 
-            final int numColumns = Math.min(numKeys, maxColumns);
-            final int topRowKeys = numKeys % numColumns;
+            final int numRows = (numKeys + maxColumns - 1) / maxColumns;
+            mNumRows = numRows;
+            final int numColumns = getOptimizedColumns(numKeys, maxColumns);
             mNumColumns = numColumns;
-            mTopRowNeedsCentering = topRowKeys != 0 && (numColumns - topRowKeys) % 2 != 0;
 
             final int numLeftKeys = (numColumns - 1) / 2;
             final int numRightKeys = numColumns - numLeftKeys; // including default key.
             final int maxLeftKeys = coordXInParent / keyWidth;
             final int maxRightKeys = Math.max(1, (parentKeyboardWidth - coordXInParent) / keyWidth);
+            int leftKeys, rightKeys;
             if (numLeftKeys > maxLeftKeys) {
-                mLeftKeys = maxLeftKeys;
-                mRightKeys = numColumns - maxLeftKeys;
+                leftKeys = maxLeftKeys;
+                rightKeys = numColumns - maxLeftKeys;
             } else if (numRightKeys > maxRightKeys) {
-                mLeftKeys = numColumns - maxRightKeys;
-                mRightKeys = maxRightKeys;
+                leftKeys = numColumns - maxRightKeys;
+                rightKeys = maxRightKeys;
             } else {
-                mLeftKeys = numLeftKeys;
-                mRightKeys = numRightKeys;
+                leftKeys = numLeftKeys;
+                rightKeys = numRightKeys;
+            }
+            // Shift right if the left edge of mini keyboard is on the edge of parent keyboard
+            // unless the parent key is on the left edge.
+            if (leftKeys * keyWidth >= coordXInParent && leftKeys > 0) {
+                leftKeys--;
+                rightKeys++;
+            }
+            // Shift left if the right edge of mini keyboard is on the edge of parent keyboard
+            // unless the parent key is on the right edge.
+            if (rightKeys * keyWidth + coordXInParent >= parentKeyboardWidth && rightKeys > 1) {
+                leftKeys++;
+                rightKeys--;
+            }
+            mLeftKeys = leftKeys;
+            mRightKeys = rightKeys;
+
+            // Centering of the top row.
+            final boolean onEdge = (leftKeys == 0 || rightKeys == 1);
+            if (numRows < 2 || onEdge || getTopRowEmptySlots(numKeys, numColumns) % 2 == 0) {
+                mTopRowAdjustment = 0;
+            } else if (mLeftKeys < mRightKeys - 1) {
+                mTopRowAdjustment = 1;
+            } else {
+                mTopRowAdjustment = -1;
             }
         }
 
@@ -113,14 +136,32 @@
             return pos;
         }
 
+        private static int getTopRowEmptySlots(int numKeys, int numColumns) {
+            final int remainingKeys = numKeys % numColumns;
+            if (remainingKeys == 0) {
+                return 0;
+            } else {
+                return numColumns - remainingKeys;
+            }
+        }
+
+        private int getOptimizedColumns(int numKeys, int maxColumns) {
+            int numColumns = Math.min(numKeys, maxColumns);
+            while (getTopRowEmptySlots(numKeys, numColumns) >= mNumRows) {
+                numColumns--;
+            }
+            return numColumns;
+        }
+
         public int getDefaultKeyCoordX() {
             return mLeftKeys * mKeyWidth;
         }
 
         public int getX(int n, int row) {
             final int x = getColumnPos(n) * mKeyWidth + getDefaultKeyCoordX();
-            if (isLastRow(row) && mTopRowNeedsCentering)
-                return x - mKeyWidth / 2;
+            if (isTopRow(row)) {
+                return x + mTopRowAdjustment * (mKeyWidth / 2);
+            }
             return x;
         }
 
@@ -131,27 +172,27 @@
         public int getRowFlags(int row) {
             int rowFlags = 0;
             if (row == 0) rowFlags |= Keyboard.EDGE_TOP;
-            if (isLastRow(row)) rowFlags |= Keyboard.EDGE_BOTTOM;
+            if (isTopRow(row)) rowFlags |= Keyboard.EDGE_BOTTOM;
             return rowFlags;
         }
 
-        private boolean isLastRow(int rowCount) {
+        private boolean isTopRow(int rowCount) {
             return rowCount == mNumRows - 1;
         }
     }
 
-    public MiniKeyboardBuilder(KeyboardView view, int layoutTemplateResId, Key popupKey) {
+    public MiniKeyboardBuilder(KeyboardView view, int layoutTemplateResId, Key parentKey) {
         final Context context = view.getContext();
         mRes = context.getResources();
         final MiniKeyboard keyboard = new MiniKeyboard(context, layoutTemplateResId, null);
         mKeyboard = keyboard;
-        mPopupCharacters = popupKey.mPopupCharacters;
+        mPopupCharacters = parentKey.mPopupCharacters;
 
         final int keyWidth = getMaxKeyWidth(view, mPopupCharacters, keyboard.getKeyWidth());
         final MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
-                mPopupCharacters.length, popupKey.mMaxPopupColumn,
+                mPopupCharacters.length, parentKey.mMaxPopupColumn,
                 keyWidth, keyboard.getRowHeight(),
-                popupKey.mX + (popupKey.mWidth + popupKey.mGap) / 2 - keyWidth / 2,
+                parentKey.mX + (parentKey.mWidth + parentKey.mGap) / 2 - keyWidth / 2,
                 view.getMeasuredWidth());
         mParams = params;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/MiniKeyboardBuilderTests.java b/tests/src/com/android/inputmethod/keyboard/MiniKeyboardBuilderTests.java
index 7e3106d..600342a 100644
--- a/tests/src/com/android/inputmethod/keyboard/MiniKeyboardBuilderTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/MiniKeyboardBuilderTests.java
@@ -25,6 +25,16 @@
     private static final int WIDTH = 10;
     private static final int HEIGHT = 10;
 
+    private static final int KEYBOARD_WIDTH = WIDTH * 10;
+    private static final int XPOS_L0 = WIDTH * 0;
+    private static final int XPOS_L1 = WIDTH * 1;
+    private static final int XPOS_L2 = WIDTH * 2;
+    private static final int XPOS_M0 = WIDTH * 5;
+    private static final int XPOS_R3 = WIDTH * 6;
+    private static final int XPOS_R2 = WIDTH * 7;
+    private static final int XPOS_R1 = WIDTH * 8;
+    private static final int XPOS_R0 = WIDTH * 9;
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -33,9 +43,8 @@
     public void testLayoutError() {
         MiniKeyboardLayoutParams params = null;
         try {
-            params = new MiniKeyboardLayoutParams(
-                    10, MAX_COLUMNS + 1, WIDTH, HEIGHT,
-                    WIDTH * 2, WIDTH * MAX_COLUMNS);
+            params = new MiniKeyboardLayoutParams(10, MAX_COLUMNS + 1, WIDTH, HEIGHT, WIDTH * 2,
+                    WIDTH * MAX_COLUMNS);
             fail("Should throw IllegalArgumentException");
         } catch (IllegalArgumentException e) {
             // Too small keyboard to hold mini keyboard.
@@ -48,39 +57,198 @@
     // "[1]" is the default key.
 
     // [1]
-    public void testLayout1Key() {
-        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
-                1, MAX_COLUMNS, WIDTH, HEIGHT,
-                WIDTH * 5, WIDTH * 10);
-        assertEquals("1 key columns", 1, params.mNumColumns);
-        assertEquals("1 key rows", 1, params.mNumRows);
-        assertEquals("1 key left", 0, params.mLeftKeys);
-        assertEquals("1 key right", 1, params.mRightKeys);
-        assertEquals("1 key [1]", 0, params.getColumnPos(0));
-        assertEquals("1 key centering", false, params.mTopRowNeedsCentering);
-        assertEquals("1 key default", 0, params.getDefaultKeyCoordX());
+    public void testLayout1KeyM0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(1, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_M0, KEYBOARD_WIDTH);
+        assertEquals("1 key M0 columns", 1, params.mNumColumns);
+        assertEquals("1 key M0 rows", 1, params.mNumRows);
+        assertEquals("1 key M0 left", 0, params.mLeftKeys);
+        assertEquals("1 key M0 right", 1, params.mRightKeys);
+        assertEquals("1 key M0 [1]", 0, params.getColumnPos(0));
+        assertEquals("1 key M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("1 key M0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |[1]
+    public void testLayout1KeyL0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(1, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L0, KEYBOARD_WIDTH);
+        assertEquals("1 key L0 columns", 1, params.mNumColumns);
+        assertEquals("1 key L0 rows", 1, params.mNumRows);
+        assertEquals("1 key L0 left", 0, params.mLeftKeys);
+        assertEquals("1 key L0 right", 1, params.mRightKeys);
+        assertEquals("1 key L0 [1]", 0, params.getColumnPos(0));
+        assertEquals("1 key L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("1 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [1]
+    public void testLayout1KeyL1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(1, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L1, KEYBOARD_WIDTH);
+        assertEquals("1 key L1 columns", 1, params.mNumColumns);
+        assertEquals("1 key L1 rows", 1, params.mNumRows);
+        assertEquals("1 key L1 left", 0, params.mLeftKeys);
+        assertEquals("1 key L1 right", 1, params.mRightKeys);
+        assertEquals("1 key L1 [1]", 0, params.getColumnPos(0));
+        assertEquals("1 key L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("1 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___ [1]
+    public void testLayout1KeyL2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(1, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L2, KEYBOARD_WIDTH);
+        assertEquals("1 key L2 columns", 1, params.mNumColumns);
+        assertEquals("1 key L2 rows", 1, params.mNumRows);
+        assertEquals("1 key L2 left", 0, params.mLeftKeys);
+        assertEquals("1 key L2 right", 1, params.mRightKeys);
+        assertEquals("1 key L2 [1]", 0, params.getColumnPos(0));
+        assertEquals("1 key L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("1 key L2 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // [1]|
+    public void testLayout1KeyR0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(1, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R0, KEYBOARD_WIDTH);
+        assertEquals("1 key R0 columns", 1, params.mNumColumns);
+        assertEquals("1 key R0 rows", 1, params.mNumRows);
+        assertEquals("1 key R0 left", 0, params.mLeftKeys);
+        assertEquals("1 key R0 right", 1, params.mRightKeys);
+        assertEquals("1 key R0 [1]", 0, params.getColumnPos(0));
+        assertEquals("1 key R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("1 key R0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // [1] ___|
+    public void testLayout1KeyR1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(1, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R1, KEYBOARD_WIDTH);
+        assertEquals("1 key R1 columns", 1, params.mNumColumns);
+        assertEquals("1 key R1 rows", 1, params.mNumRows);
+        assertEquals("1 key R1 left", 0, params.mLeftKeys);
+        assertEquals("1 key R1 right", 1, params.mRightKeys);
+        assertEquals("1 key R1 [1]", 0, params.getColumnPos(0));
+        assertEquals("1 key R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("1 key R1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // [1] ___ ___|
+    public void testLayout1KeyR2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(1, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R2, KEYBOARD_WIDTH);
+        assertEquals("1 key R2 columns", 1, params.mNumColumns);
+        assertEquals("1 key R2 rows", 1, params.mNumRows);
+        assertEquals("1 key R2 left", 0, params.mLeftKeys);
+        assertEquals("1 key R2 right", 1, params.mRightKeys);
+        assertEquals("1 key R2 [1]", 0, params.getColumnPos(0));
+        assertEquals("1 key R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("1 key R2 default", WIDTH * 0, params.getDefaultKeyCoordX());
     }
 
     // [1] [2]
-    public void testLayout2Key() {
-        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
-                2, MAX_COLUMNS, WIDTH, HEIGHT,
-                WIDTH * 5, WIDTH * 10);
-        assertEquals("2 key columns", 2, params.mNumColumns);
-        assertEquals("2 key rows", 1, params.mNumRows);
-        assertEquals("2 key left", 0, params.mLeftKeys);
-        assertEquals("2 key right", 2, params.mRightKeys);
-        assertEquals("2 key [1]", 0, params.getColumnPos(0));
-        assertEquals("2 key [2]", 1, params.getColumnPos(1));
-        assertEquals("2 key centering", false, params.mTopRowNeedsCentering);
-        assertEquals("2 key default", 0, params.getDefaultKeyCoordX());
+    public void testLayout2KeyM0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(2, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_M0, KEYBOARD_WIDTH);
+        assertEquals("2 key M0 columns", 2, params.mNumColumns);
+        assertEquals("2 key M0 rows", 1, params.mNumRows);
+        assertEquals("2 key M0 left", 0, params.mLeftKeys);
+        assertEquals("2 key M0 right", 2, params.mRightKeys);
+        assertEquals("2 key M0 [1]", 0, params.getColumnPos(0));
+        assertEquals("2 key M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("2 key M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("2 key M0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |[1] [2]
+    public void testLayout2KeyL0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(2, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L0, KEYBOARD_WIDTH);
+        assertEquals("2 key L0 columns", 2, params.mNumColumns);
+        assertEquals("2 key L0 rows", 1, params.mNumRows);
+        assertEquals("2 key L0 left", 0, params.mLeftKeys);
+        assertEquals("2 key L0 right", 2, params.mRightKeys);
+        assertEquals("2 key L0 [1]", 0, params.getColumnPos(0));
+        assertEquals("2 key L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("2 key L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("2 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [1] [2]
+    public void testLayout2KeyL1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(2, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L1, KEYBOARD_WIDTH);
+        assertEquals("2 key L1 columns", 2, params.mNumColumns);
+        assertEquals("2 key L1 rows", 1, params.mNumRows);
+        assertEquals("2 key L1 left", 0, params.mLeftKeys);
+        assertEquals("2 key L1 right", 2, params.mRightKeys);
+        assertEquals("2 key L1 [1]", 0, params.getColumnPos(0));
+        assertEquals("2 key L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("2 key L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("2 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___ [1] [2]
+    public void testLayout2KeyL2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(2, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L2, KEYBOARD_WIDTH);
+        assertEquals("2 key L2 columns", 2, params.mNumColumns);
+        assertEquals("2 key L2 rows", 1, params.mNumRows);
+        assertEquals("2 key L2 left", 0, params.mLeftKeys);
+        assertEquals("2 key L2 right", 2, params.mRightKeys);
+        assertEquals("2 key L2 [1]", 0, params.getColumnPos(0));
+        assertEquals("2 key L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("2 key L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("2 key L2 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // [2] [1]|
+    public void testLayout2KeyR0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(2, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R0, KEYBOARD_WIDTH);
+        assertEquals("2 key R0 columns", 2, params.mNumColumns);
+        assertEquals("2 key R0 rows", 1, params.mNumRows);
+        assertEquals("2 key R0 left", 1, params.mLeftKeys);
+        assertEquals("2 key R0 right", 1, params.mRightKeys);
+        assertEquals("2 key R0 [1]", 0, params.getColumnPos(0));
+        assertEquals("2 key R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("2 key R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("2 key R0 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [2] [1] ___|
+    public void testLayout2KeyR1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(2, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R1, KEYBOARD_WIDTH);
+        assertEquals("2 key R1 columns", 2, params.mNumColumns);
+        assertEquals("2 key R1 rows", 1, params.mNumRows);
+        assertEquals("2 key R1 left", 1, params.mLeftKeys);
+        assertEquals("2 key R1 right", 1, params.mRightKeys);
+        assertEquals("2 key R1 [1]", 0, params.getColumnPos(0));
+        assertEquals("2 key R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("2 key R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("2 key R1 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [1] [2] ___ ___|
+    public void testLayout2KeyR2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(2, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R2, KEYBOARD_WIDTH);
+        assertEquals("2 key R2 columns", 2, params.mNumColumns);
+        assertEquals("2 key R2 rows", 1, params.mNumRows);
+        assertEquals("2 key R2 left", 0, params.mLeftKeys);
+        assertEquals("2 key R2 right", 2, params.mRightKeys);
+        assertEquals("2 key R2 [1]", 0, params.getColumnPos(0));
+        assertEquals("2 key R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("2 key R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("2 key R2 default", WIDTH * 0, params.getDefaultKeyCoordX());
     }
 
     // [3] [1] [2]
-    public void testLayout3Key() {
-        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
-                3, MAX_COLUMNS, WIDTH, HEIGHT,
-                WIDTH * 5, WIDTH * 10);
+    public void testLayout3KeyM0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(3, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_M0, KEYBOARD_WIDTH);
         assertEquals("3 key columns", 3, params.mNumColumns);
         assertEquals("3 key rows", 1, params.mNumRows);
         assertEquals("3 key left", 1, params.mLeftKeys);
@@ -88,15 +256,104 @@
         assertEquals("3 key [1]", 0, params.getColumnPos(0));
         assertEquals("3 key [2]", 1, params.getColumnPos(1));
         assertEquals("3 key [3]", -1, params.getColumnPos(2));
-        assertEquals("3 key centering", false, params.mTopRowNeedsCentering);
-        assertEquals("3 key default", WIDTH, params.getDefaultKeyCoordX());
+        assertEquals("3 key adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // |[1] [2] [3]
+    public void testLayout3KeyL0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(3, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L0, KEYBOARD_WIDTH);
+        assertEquals("3 key L0 columns", 3, params.mNumColumns);
+        assertEquals("3 key L0 rows", 1, params.mNumRows);
+        assertEquals("3 key L0 left", 0, params.mLeftKeys);
+        assertEquals("3 key L0 right", 3, params.mRightKeys);
+        assertEquals("3 key L0 [1]", 0, params.getColumnPos(0));
+        assertEquals("3 key L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("3 key L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("3 key L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [1] [2] [3]
+    public void testLayout3KeyL1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(3, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L1, KEYBOARD_WIDTH);
+        assertEquals("3 key L1 columns", 3, params.mNumColumns);
+        assertEquals("3 key L1 rows", 1, params.mNumRows);
+        assertEquals("3 key L1 left", 0, params.mLeftKeys);
+        assertEquals("3 key L1 right", 3, params.mRightKeys);
+        assertEquals("3 key L1 [1]", 0, params.getColumnPos(0));
+        assertEquals("3 key L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("3 key L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("3 key L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___ [3] [1] [2]
+    public void testLayout3KeyL2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(3, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L2, KEYBOARD_WIDTH);
+        assertEquals("3 key L2 columns", 3, params.mNumColumns);
+        assertEquals("3 key L2 rows", 1, params.mNumRows);
+        assertEquals("3 key L2 left", 1, params.mLeftKeys);
+        assertEquals("3 key L2 right", 2, params.mRightKeys);
+        assertEquals("3 key L2 [1]", 0, params.getColumnPos(0));
+        assertEquals("3 key L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("3 key L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("3 key L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [3] [2] [1]|
+    public void testLayout3KeyR0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(3, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R0, KEYBOARD_WIDTH);
+        assertEquals("3 key R0 columns", 3, params.mNumColumns);
+        assertEquals("3 key R0 rows", 1, params.mNumRows);
+        assertEquals("3 key R0 left", 2, params.mLeftKeys);
+        assertEquals("3 key R0 right", 1, params.mRightKeys);
+        assertEquals("3 key R0 [1]", 0, params.getColumnPos(0));
+        assertEquals("3 key R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("3 key R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("3 key R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key R0 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    // [3] [2] [1] ___|
+    public void testLayout3KeyR1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(3, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R1, KEYBOARD_WIDTH);
+        assertEquals("3 key R1 columns", 3, params.mNumColumns);
+        assertEquals("3 key R1 rows", 1, params.mNumRows);
+        assertEquals("3 key R1 left", 2, params.mLeftKeys);
+        assertEquals("3 key R1 right", 1, params.mRightKeys);
+        assertEquals("3 key R1 [1]", 0, params.getColumnPos(0));
+        assertEquals("3 key R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("3 key R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("3 key R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key R1 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    // [3] [1] [2] ___ ___|
+    public void testLayout3KeyR2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(3, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R2, KEYBOARD_WIDTH);
+        assertEquals("3 key R2 columns", 3, params.mNumColumns);
+        assertEquals("3 key R2 rows", 1, params.mNumRows);
+        assertEquals("3 key R2 left", 1, params.mLeftKeys);
+        assertEquals("3 key R2 right", 2, params.mRightKeys);
+        assertEquals("3 key R2 [1]", 0, params.getColumnPos(0));
+        assertEquals("3 key R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("3 key R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("3 key R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key R2 default", WIDTH * 1, params.getDefaultKeyCoordX());
     }
 
     // [3] [1] [2] [4]
-    public void testLayout4Key() {
-        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
-                4, MAX_COLUMNS, WIDTH, HEIGHT,
-                WIDTH * 5, WIDTH * 10);
+    public void testLayout4KeyM0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(4, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_M0, KEYBOARD_WIDTH);
         assertEquals("4 key columns", 4, params.mNumColumns);
         assertEquals("4 key rows", 1, params.mNumRows);
         assertEquals("4 key left", 1, params.mLeftKeys);
@@ -105,15 +362,110 @@
         assertEquals("4 key [2]", 1, params.getColumnPos(1));
         assertEquals("4 key [3]", -1, params.getColumnPos(2));
         assertEquals("4 key [4]", 2, params.getColumnPos(3));
-        assertEquals("4 key centering", false, params.mTopRowNeedsCentering);
-        assertEquals("4 key default", WIDTH, params.getDefaultKeyCoordX());
+        assertEquals("4 key adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // |[1] [2] [3] [4]
+    public void testLayout4KeyL0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(4, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L0, KEYBOARD_WIDTH);
+        assertEquals("4 key L0 columns", 4, params.mNumColumns);
+        assertEquals("4 key L0 rows", 1, params.mNumRows);
+        assertEquals("4 key L0 left", 0, params.mLeftKeys);
+        assertEquals("4 key L0 right", 4, params.mRightKeys);
+        assertEquals("4 key L0 [1]", 0, params.getColumnPos(0));
+        assertEquals("4 key L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("4 key L0 [4]", 3, params.getColumnPos(3));
+        assertEquals("4 key L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [1] [2] [3] [4]
+    public void testLayout4KeyL1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(4, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L1, KEYBOARD_WIDTH);
+        assertEquals("4 key L1 columns", 4, params.mNumColumns);
+        assertEquals("4 key L1 rows", 1, params.mNumRows);
+        assertEquals("4 key L1 left", 0, params.mLeftKeys);
+        assertEquals("4 key L1 right", 4, params.mRightKeys);
+        assertEquals("4 key L1 [1]", 0, params.getColumnPos(0));
+        assertEquals("4 key L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("4 key L1 [4]", 3, params.getColumnPos(3));
+        assertEquals("4 key L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___ [3] [1] [2] [4]
+    public void testLayout4KeyL2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(4, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L2, KEYBOARD_WIDTH);
+        assertEquals("4 key L2 columns", 4, params.mNumColumns);
+        assertEquals("4 key L2 rows", 1, params.mNumRows);
+        assertEquals("4 key L2 left", 1, params.mLeftKeys);
+        assertEquals("4 key L2 right", 3, params.mRightKeys);
+        assertEquals("4 key L2 [1]", 0, params.getColumnPos(0));
+        assertEquals("4 key L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("4 key L2 [4]", 2, params.getColumnPos(3));
+        assertEquals("4 key L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [4] [3] [2] [1]|
+    public void testLayout4KeyR0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(4, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R0, KEYBOARD_WIDTH);
+        assertEquals("4 key R0 columns", 4, params.mNumColumns);
+        assertEquals("4 key R0 rows", 1, params.mNumRows);
+        assertEquals("4 key R0 left", 3, params.mLeftKeys);
+        assertEquals("4 key R0 right", 1, params.mRightKeys);
+        assertEquals("4 key R0 [1]", 0, params.getColumnPos(0));
+        assertEquals("4 key R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("4 key R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("4 key R0 [4]", -3, params.getColumnPos(3));
+        assertEquals("4 key R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key R0 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    // [4] [3] [2] [1] ___|
+    public void testLayout4KeyR1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(4, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R1, KEYBOARD_WIDTH);
+        assertEquals("4 key R1 columns", 4, params.mNumColumns);
+        assertEquals("4 key R1 rows", 1, params.mNumRows);
+        assertEquals("4 key R1 left", 3, params.mLeftKeys);
+        assertEquals("4 key R1 right", 1, params.mRightKeys);
+        assertEquals("4 key R1 [1]", 0, params.getColumnPos(0));
+        assertEquals("4 key R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("4 key R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("4 key R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("4 key R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key R1 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    // [4] [3] [1] [2] ___ ___|
+    public void testLayout4KeyR2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(4, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R2, KEYBOARD_WIDTH);
+        assertEquals("4 key R2 columns", 4, params.mNumColumns);
+        assertEquals("4 key R2 rows", 1, params.mNumRows);
+        assertEquals("4 key R2 left", 2, params.mLeftKeys);
+        assertEquals("4 key R2 right", 2, params.mRightKeys);
+        assertEquals("4 key R2 [1]", 0, params.getColumnPos(0));
+        assertEquals("4 key R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("4 key R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("4 key R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key R2 default", WIDTH * 2, params.getDefaultKeyCoordX());
     }
 
     // [5] [3] [1] [2] [4]
-    public void testLayout5Key() {
-        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
-                5, MAX_COLUMNS, WIDTH, HEIGHT,
-                WIDTH * 5, WIDTH * 10);
+    public void testLayout5KeyM0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(5, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_M0, KEYBOARD_WIDTH);
         assertEquals("5 key columns", 5, params.mNumColumns);
         assertEquals("5 key rows", 1, params.mNumRows);
         assertEquals("5 key left", 2, params.mLeftKeys);
@@ -123,190 +475,942 @@
         assertEquals("5 key [3]", -1, params.getColumnPos(2));
         assertEquals("5 key [4]", 2, params.getColumnPos(3));
         assertEquals("5 key [5]", -2, params.getColumnPos(4));
-        assertEquals("5 key centering", false, params.mTopRowNeedsCentering);
+        assertEquals("5 key adjust", 0, params.mTopRowAdjustment);
         assertEquals("5 key default", WIDTH * 2, params.getDefaultKeyCoordX());
     }
 
-    //         [6]
-    // [5] [3] [1] [2] [4]
-    public void testLayout6Key() {
-        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
-                6, MAX_COLUMNS, WIDTH, HEIGHT,
-                WIDTH * 5, WIDTH * 10);
-        assertEquals("6 key columns", 5, params.mNumColumns);
+    // |[1] [2] [3] [4] [5]
+    public void testLayout5KeyL0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(5, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L0, KEYBOARD_WIDTH);
+        assertEquals("5 key L0 columns", 5, params.mNumColumns);
+        assertEquals("5 key L0 rows", 1, params.mNumRows);
+        assertEquals("5 key L0 left", 0, params.mLeftKeys);
+        assertEquals("5 key L0 right", 5, params.mRightKeys);
+        assertEquals("5 key L0 [1]", 0, params.getColumnPos(0));
+        assertEquals("5 key L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("5 key L0 [4]", 3, params.getColumnPos(3));
+        assertEquals("5 key L0 [5]", 4, params.getColumnPos(4));
+        assertEquals("5 key L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [1] [2] [3] [4] [5]
+    public void testLayout5KeyL1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(5, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L1, KEYBOARD_WIDTH);
+        assertEquals("5 key L1 columns", 5, params.mNumColumns);
+        assertEquals("5 key L1 rows", 1, params.mNumRows);
+        assertEquals("5 key L1 left", 0, params.mLeftKeys);
+        assertEquals("5 key L1 right", 5, params.mRightKeys);
+        assertEquals("5 key L1 [1]", 0, params.getColumnPos(0));
+        assertEquals("5 key L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("5 key L1 [4]", 3, params.getColumnPos(3));
+        assertEquals("5 key L1 [5]", 4, params.getColumnPos(4));
+        assertEquals("5 key L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___ [3] [1] [2] [4] [5]
+    public void testLayout5KeyL2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(5, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L2, KEYBOARD_WIDTH);
+        assertEquals("5 key L2 columns", 5, params.mNumColumns);
+        assertEquals("5 key L2 rows", 1, params.mNumRows);
+        assertEquals("5 key L2 left", 1, params.mLeftKeys);
+        assertEquals("5 key L2 right", 4, params.mRightKeys);
+        assertEquals("5 key L2 [1]", 0, params.getColumnPos(0));
+        assertEquals("5 key L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("5 key L2 [4]", 2, params.getColumnPos(3));
+        assertEquals("5 key L2 [5]", 3, params.getColumnPos(4));
+        assertEquals("5 key L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [5] [4] [3] [2] [1]|
+    public void testLayout5KeyR0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(5, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R0, KEYBOARD_WIDTH);
+        assertEquals("5 key R0 columns", 5, params.mNumColumns);
+        assertEquals("5 key R0 rows", 1, params.mNumRows);
+        assertEquals("5 key R0 left", 4, params.mLeftKeys);
+        assertEquals("5 key R0 right", 1, params.mRightKeys);
+        assertEquals("5 key R0 [1]", 0, params.getColumnPos(0));
+        assertEquals("5 key R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("5 key R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("5 key R0 [4]", -3, params.getColumnPos(3));
+        assertEquals("5 key R0 [5]", -4, params.getColumnPos(4));
+        assertEquals("5 key R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key R0 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    // [5] [4] [3] [2] [1] ___|
+    public void testLayout5KeyR1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(5, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R1, KEYBOARD_WIDTH);
+        assertEquals("5 key R1 columns", 5, params.mNumColumns);
+        assertEquals("5 key R1 rows", 1, params.mNumRows);
+        assertEquals("5 key R1 left", 4, params.mLeftKeys);
+        assertEquals("5 key R1 right", 1, params.mRightKeys);
+        assertEquals("5 key R1 [1]", 0, params.getColumnPos(0));
+        assertEquals("5 key R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("5 key R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("5 key R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("5 key R1 [5]", -4, params.getColumnPos(4));
+        assertEquals("5 key R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key R1 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    // [5] [4] [3] [1] [2] ___ ___|
+    public void testLayout5KeyR2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(5, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R2, KEYBOARD_WIDTH);
+        assertEquals("5 key R2 columns", 5, params.mNumColumns);
+        assertEquals("5 key R2 rows", 1, params.mNumRows);
+        assertEquals("5 key R2 left", 3, params.mLeftKeys);
+        assertEquals("5 key R2 right", 2, params.mRightKeys);
+        assertEquals("5 key R2 [1]", 0, params.getColumnPos(0));
+        assertEquals("5 key R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("5 key R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("5 key R2 [5]", -3, params.getColumnPos(4));
+        assertEquals("5 key R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key R2 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    // [6] [4] [5]
+    // [3] [1] [2]
+    public void testLayout6KeyM0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(6, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_M0, KEYBOARD_WIDTH);
+        assertEquals("6 key columns", 3, params.mNumColumns);
         assertEquals("6 key rows", 2, params.mNumRows);
-        assertEquals("6 key left", 2, params.mLeftKeys);
-        assertEquals("6 key right", 3, params.mRightKeys);
+        assertEquals("6 key left", 1, params.mLeftKeys);
+        assertEquals("6 key right", 2, params.mRightKeys);
         assertEquals("6 key [1]", 0, params.getColumnPos(0));
         assertEquals("6 key [2]", 1, params.getColumnPos(1));
         assertEquals("6 key [3]", -1, params.getColumnPos(2));
-        assertEquals("6 key [4]", 2, params.getColumnPos(3));
-        assertEquals("6 key [5]", -2, params.getColumnPos(4));
-        assertEquals("6 key [6]", 0, params.getColumnPos(5));
-        assertEquals("6 key centering", false, params.mTopRowNeedsCentering);
-        assertEquals("6 key default", WIDTH * 2, params.getDefaultKeyCoordX());
+        assertEquals("6 key [4]", 0, params.getColumnPos(3));
+        assertEquals("6 key [5]", 1, params.getColumnPos(4));
+        assertEquals("6 key [6]", -1, params.getColumnPos(5));
+        assertEquals("6 key adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key default", WIDTH * 1, params.getDefaultKeyCoordX());
     }
 
-    //       [6] [7]
-    // [5] [3] [1] [2] [4]
-    public void testLayout7Key() {
-        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
-                7, MAX_COLUMNS, WIDTH, HEIGHT,
-                WIDTH * 5, WIDTH * 10);
-        assertEquals("7 key columns", 5, params.mNumColumns);
+    // |[4] [5] [6]
+    // |[1] [2] [3]
+    public void testLayout6KeyL0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(6, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L0, KEYBOARD_WIDTH);
+        assertEquals("6 key L0 columns", 3, params.mNumColumns);
+        assertEquals("6 key L0 rows", 2, params.mNumRows);
+        assertEquals("6 key L0 left", 0, params.mLeftKeys);
+        assertEquals("6 key L0 right", 3, params.mRightKeys);
+        assertEquals("6 key L0 [1]", 0, params.getColumnPos(0));
+        assertEquals("6 key L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("6 key L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("6 key L0 [4]", 0, params.getColumnPos(3));
+        assertEquals("6 key L0 [5]", 1, params.getColumnPos(4));
+        assertEquals("6 key L0 [6]", 2, params.getColumnPos(5));
+        assertEquals("6 key L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [4] [5] [6]
+    // |___ [1] [2] [3]
+    public void testLayout6KeyL1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(6, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L1, KEYBOARD_WIDTH);
+        assertEquals("6 key L1 columns", 3, params.mNumColumns);
+        assertEquals("6 key L1 rows", 2, params.mNumRows);
+        assertEquals("6 key L1 left", 0, params.mLeftKeys);
+        assertEquals("6 key L1 right", 3, params.mRightKeys);
+        assertEquals("6 key L1 [1]", 0, params.getColumnPos(0));
+        assertEquals("6 key L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("6 key L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("6 key L1 [4]", 0, params.getColumnPos(3));
+        assertEquals("6 key L1 [5]", 1, params.getColumnPos(4));
+        assertEquals("6 key L1 [6]", 2, params.getColumnPos(5));
+        assertEquals("6 key L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___ [6] [4] [5]
+    // |___ ___ [3] [1] [2]
+    public void testLayout6KeyL2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(6, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L2, KEYBOARD_WIDTH);
+        assertEquals("6 key L2 columns", 3, params.mNumColumns);
+        assertEquals("6 key L2 rows", 2, params.mNumRows);
+        assertEquals("6 key L2 left", 1, params.mLeftKeys);
+        assertEquals("6 key L2 right", 2, params.mRightKeys);
+        assertEquals("6 key L2 [1]", 0, params.getColumnPos(0));
+        assertEquals("6 key L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("6 key L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("6 key L2 [4]", 0, params.getColumnPos(3));
+        assertEquals("6 key L2 [5]", 1, params.getColumnPos(4));
+        assertEquals("6 key L2 [6]", -1, params.getColumnPos(5));
+        assertEquals("6 key L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [6] [5] [4]|
+    // [3] [2] [1]|
+    public void testLayout6KeyR0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(6, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R0, KEYBOARD_WIDTH);
+        assertEquals("6 key R0 columns", 3, params.mNumColumns);
+        assertEquals("6 key R0 rows", 2, params.mNumRows);
+        assertEquals("6 key R0 left", 2, params.mLeftKeys);
+        assertEquals("6 key R0 right", 1, params.mRightKeys);
+        assertEquals("6 key R0 [1]", 0, params.getColumnPos(0));
+        assertEquals("6 key R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("6 key R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("6 key R0 [4]", 0, params.getColumnPos(3));
+        assertEquals("6 key R0 [5]", -1, params.getColumnPos(4));
+        assertEquals("6 key R0 [6]", -2, params.getColumnPos(5));
+        assertEquals("6 key R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key R0 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    // [6] [5] [4] ___|
+    // [3] [2] [1] ___|
+    public void testLayout6KeyR1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(6, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R1, KEYBOARD_WIDTH);
+        assertEquals("6 key R1 columns", 3, params.mNumColumns);
+        assertEquals("6 key R1 rows", 2, params.mNumRows);
+        assertEquals("6 key R1 left", 2, params.mLeftKeys);
+        assertEquals("6 key R1 right", 1, params.mRightKeys);
+        assertEquals("6 key R1 [1]", 0, params.getColumnPos(0));
+        assertEquals("6 key R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("6 key R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("6 key R1 [4]", 0, params.getColumnPos(3));
+        assertEquals("6 key R1 [5]", -1, params.getColumnPos(4));
+        assertEquals("6 key R1 [6]", -2, params.getColumnPos(5));
+        assertEquals("6 key R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key R1 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    // [6] [4] [5] ___ ___|
+    // [3] [1] [2] ___ ___|
+    public void testLayout6KeyR2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(6, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R2, KEYBOARD_WIDTH);
+        assertEquals("6 key R2 columns", 3, params.mNumColumns);
+        assertEquals("6 key R2 rows", 2, params.mNumRows);
+        assertEquals("6 key R2 left", 1, params.mLeftKeys);
+        assertEquals("6 key R2 right", 2, params.mRightKeys);
+        assertEquals("6 key R2 [1]", 0, params.getColumnPos(0));
+        assertEquals("6 key R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("6 key R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("6 key R2 [4]", 0, params.getColumnPos(3));
+        assertEquals("6 key R2 [5]", 1, params.getColumnPos(4));
+        assertEquals("6 key R2 [6]", -1, params.getColumnPos(5));
+        assertEquals("6 key R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key R2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    //   [7] [5] [6]
+    // [3] [1] [2] [4]
+    public void testLayout7KeyM0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(7, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_M0, KEYBOARD_WIDTH);
+        assertEquals("7 key columns", 4, params.mNumColumns);
         assertEquals("7 key rows", 2, params.mNumRows);
-        assertEquals("7 key left", 2, params.mLeftKeys);
+        assertEquals("7 key left", 1, params.mLeftKeys);
         assertEquals("7 key right", 3, params.mRightKeys);
         assertEquals("7 key [1]", 0, params.getColumnPos(0));
         assertEquals("7 key [2]", 1, params.getColumnPos(1));
         assertEquals("7 key [3]", -1, params.getColumnPos(2));
         assertEquals("7 key [4]", 2, params.getColumnPos(3));
-        assertEquals("7 key [5]", -2, params.getColumnPos(4));
-        assertEquals("7 key [6]", 0, params.getColumnPos(5));
-        assertEquals("7 key [7]", 1, params.getColumnPos(6));
-        assertEquals("7 key centering", true, params.mTopRowNeedsCentering);
-        assertEquals("7 key default", WIDTH * 2, params.getDefaultKeyCoordX());
+        assertEquals("7 key [5]", 0, params.getColumnPos(4));
+        assertEquals("7 key [6]", 1, params.getColumnPos(5));
+        assertEquals("7 key [7]", -1, params.getColumnPos(6));
+        assertEquals("7 key adjust", 1, params.mTopRowAdjustment);
+        assertEquals("7 key default", WIDTH * 1, params.getDefaultKeyCoordX());
     }
 
-    //     [8] [6] [7]
-    // [5] [3] [1] [2] [4]
-    public void testLayout8Key() {
-        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
-                8, MAX_COLUMNS, WIDTH, HEIGHT,
-                WIDTH * 5, WIDTH * 10);
-        assertEquals("8 key columns", 5, params.mNumColumns);
-        assertEquals("8 key rows", 2, params.mNumRows);
-        assertEquals("8 key left", 2, params.mLeftKeys);
-        assertEquals("8 key right", 3, params.mRightKeys);
-        assertEquals("8 key [1]", 0, params.getColumnPos(0));
-        assertEquals("8 key [2]", 1, params.getColumnPos(1));
-        assertEquals("8 key [3]", -1, params.getColumnPos(2));
-        assertEquals("8 key [4]", 2, params.getColumnPos(3));
-        assertEquals("8 key [5]", -2, params.getColumnPos(4));
-        assertEquals("8 key [6]", 0, params.getColumnPos(5));
-        assertEquals("8 key [7]", 1, params.getColumnPos(6));
-        assertEquals("8 key [8]", -1, params.getColumnPos(7));
-        assertEquals("8 key centering", false, params.mTopRowNeedsCentering);
-        assertEquals("8 key default", WIDTH * 2, params.getDefaultKeyCoordX());
+    // |[5] [6] [7]
+    // |[1] [2] [3] [4]
+    public void testLayout7KeyL0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(7, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L0, KEYBOARD_WIDTH);
+        assertEquals("7 key L0 columns", 4, params.mNumColumns);
+        assertEquals("7 key L0 rows", 2, params.mNumRows);
+        assertEquals("7 key L0 left", 0, params.mLeftKeys);
+        assertEquals("7 key L0 right", 4, params.mRightKeys);
+        assertEquals("7 key L0 [1]", 0, params.getColumnPos(0));
+        assertEquals("7 key L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("7 key L0 [4]", 3, params.getColumnPos(3));
+        assertEquals("7 key L0 [5]", 0, params.getColumnPos(4));
+        assertEquals("7 key L0 [6]", 1, params.getColumnPos(5));
+        assertEquals("7 key L0 [7]", 2, params.getColumnPos(6));
+        assertEquals("7 key L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [5] [6] [7]
+    // |___ [1] [2] [3] [4]
+    public void testLayout7KeyL1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(7, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L1, KEYBOARD_WIDTH);
+        assertEquals("7 key L1 columns", 4, params.mNumColumns);
+        assertEquals("7 key L1 rows", 2, params.mNumRows);
+        assertEquals("7 key L1 left", 0, params.mLeftKeys);
+        assertEquals("7 key L1 right", 4, params.mRightKeys);
+        assertEquals("7 key L1 [1]", 0, params.getColumnPos(0));
+        assertEquals("7 key L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("7 key L1 [4]", 3, params.getColumnPos(3));
+        assertEquals("7 key L1 [5]", 0, params.getColumnPos(4));
+        assertEquals("7 key L1 [6]", 1, params.getColumnPos(5));
+        assertEquals("7 key L1 [7]", 2, params.getColumnPos(6));
+        assertEquals("7 key L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___   [7] [5] [6]
+    // |___ ___ [3] [1] [2] [4]
+    public void testLayout7KeyL2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(7, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L2, KEYBOARD_WIDTH);
+        assertEquals("7 key L2 columns", 4, params.mNumColumns);
+        assertEquals("7 key L2 rows", 2, params.mNumRows);
+        assertEquals("7 key L2 left", 1, params.mLeftKeys);
+        assertEquals("7 key L2 right", 3, params.mRightKeys);
+        assertEquals("7 key L2 [1]", 0, params.getColumnPos(0));
+        assertEquals("7 key L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("7 key L2 [4]", 2, params.getColumnPos(3));
+        assertEquals("7 key L2 [5]", 0, params.getColumnPos(4));
+        assertEquals("7 key L2 [6]", 1, params.getColumnPos(5));
+        assertEquals("7 key L2 [7]", -1, params.getColumnPos(6));
+        assertEquals("7 key L2 adjust", 1, params.mTopRowAdjustment);
+        assertEquals("7 key L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    //     [7] [6] [5]|
+    // [4] [3] [2] [1]|
+    public void testLayout7KeyR0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(7, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R0, KEYBOARD_WIDTH);
+        assertEquals("7 key R0 columns", 4, params.mNumColumns);
+        assertEquals("7 key R0 rows", 2, params.mNumRows);
+        assertEquals("7 key R0 left", 3, params.mLeftKeys);
+        assertEquals("7 key R0 right", 1, params.mRightKeys);
+        assertEquals("7 key R0 [1]", 0, params.getColumnPos(0));
+        assertEquals("7 key R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("7 key R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("7 key R0 [4]", -3, params.getColumnPos(3));
+        assertEquals("7 key R0 [5]", 0, params.getColumnPos(4));
+        assertEquals("7 key R0 [6]", -1, params.getColumnPos(5));
+        assertEquals("7 key R0 [7]", -2, params.getColumnPos(6));
+        assertEquals("7 key R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key R0 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    //     [7] [6] [5] ___|
+    // [4] [3] [2] [1] ___|
+    public void testLayout7KeyR1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(7, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R1, KEYBOARD_WIDTH);
+        assertEquals("7 key R1 columns", 4, params.mNumColumns);
+        assertEquals("7 key R1 rows", 2, params.mNumRows);
+        assertEquals("7 key R1 left", 3, params.mLeftKeys);
+        assertEquals("7 key R1 right", 1, params.mRightKeys);
+        assertEquals("7 key R1 [1]", 0, params.getColumnPos(0));
+        assertEquals("7 key R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("7 key R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("7 key R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("7 key R1 [5]", 0, params.getColumnPos(4));
+        assertEquals("7 key R1 [6]", -1, params.getColumnPos(5));
+        assertEquals("7 key R1 [7]", -2, params.getColumnPos(6));
+        assertEquals("7 key R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key R1 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    //   [7] [5] [6]   ___ ___|
+    // [4] [3] [1] [2] ___ ___|
+    public void testLayout7KeyR2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(7, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R2, KEYBOARD_WIDTH);
+        assertEquals("7 key R2 columns", 4, params.mNumColumns);
+        assertEquals("7 key R2 rows", 2, params.mNumRows);
+        assertEquals("7 key R2 left", 2, params.mLeftKeys);
+        assertEquals("7 key R2 right", 2, params.mRightKeys);
+        assertEquals("7 key R2 [1]", 0, params.getColumnPos(0));
+        assertEquals("7 key R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("7 key R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("7 key R2 [5]", 0, params.getColumnPos(4));
+        assertEquals("7 key R2 [6]", 1, params.getColumnPos(5));
+        assertEquals("7 key R2 [7]", -1, params.getColumnPos(6));
+        assertEquals("7 key R2 adjust", -1, params.mTopRowAdjustment);
+        assertEquals("7 key R2 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    // [7] [6] [5] [3] [1] [2] [4] ___|
+    public void testLayout7KeyR3Max7() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(7, 7, WIDTH,
+                HEIGHT, XPOS_R3, KEYBOARD_WIDTH);
+        assertEquals("7 key R2 columns", 7, params.mNumColumns);
+        assertEquals("7 key R2 rows", 1, params.mNumRows);
+        assertEquals("7 key R2 left", 4, params.mLeftKeys);
+        assertEquals("7 key R2 right", 3, params.mRightKeys);
+        assertEquals("7 key R2 [1]", 0, params.getColumnPos(0));
+        assertEquals("7 key R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("7 key R2 [4]", 2, params.getColumnPos(3));
+        assertEquals("7 key R2 [5]", -2, params.getColumnPos(4));
+        assertEquals("7 key R2 [6]", -3, params.getColumnPos(5));
+        assertEquals("7 key R2 [7]", -4, params.getColumnPos(6));
+        assertEquals("7 key R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key R2 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    // [7] [5] [6] [8]
+    // [3] [1] [2] [4]
+    public void testLayout8KeyM0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(8, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_M0, KEYBOARD_WIDTH);
+        assertEquals("8 key M0 columns", 4, params.mNumColumns);
+        assertEquals("8 key M0 rows", 2, params.mNumRows);
+        assertEquals("8 key M0 left", 1, params.mLeftKeys);
+        assertEquals("8 key M0 right", 3, params.mRightKeys);
+        assertEquals("8 key M0 [1]", 0, params.getColumnPos(0));
+        assertEquals("8 key M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("8 key M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("8 key M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("8 key M0 [5]", 0, params.getColumnPos(4));
+        assertEquals("8 key M0 [6]", 1, params.getColumnPos(5));
+        assertEquals("8 key M0 [7]", -1, params.getColumnPos(6));
+        assertEquals("8 key M0 [8]", 2, params.getColumnPos(7));
+        assertEquals("8 key M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("8 key M0 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // |[5] [6] [7] [8]
+    // |[1] [2] [3] [4]
+    public void testLayout8KeyL0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(8, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L0, KEYBOARD_WIDTH);
+        assertEquals("8 key L0 columns", 4, params.mNumColumns);
+        assertEquals("8 key L0 rows", 2, params.mNumRows);
+        assertEquals("8 key L0 left", 0, params.mLeftKeys);
+        assertEquals("8 key L0 right", 4, params.mRightKeys);
+        assertEquals("8 key L0 [1]", 0, params.getColumnPos(0));
+        assertEquals("8 key L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("8 key L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("8 key L0 [4]", 3, params.getColumnPos(3));
+        assertEquals("8 key L0 [5]", 0, params.getColumnPos(4));
+        assertEquals("8 key L0 [6]", 1, params.getColumnPos(5));
+        assertEquals("8 key L0 [7]", 2, params.getColumnPos(6));
+        assertEquals("8 key L0 [8]", 3, params.getColumnPos(7));
+        assertEquals("8 key L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("8 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [5] [6] [7] [8]
+    // |___ [1] [2] [3] [4]
+    public void testLayout8KeyL1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(8, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L1, KEYBOARD_WIDTH);
+        assertEquals("8 key L1 columns", 4, params.mNumColumns);
+        assertEquals("8 key L1 rows", 2, params.mNumRows);
+        assertEquals("8 key L1 left", 0, params.mLeftKeys);
+        assertEquals("8 key L1 right", 4, params.mRightKeys);
+        assertEquals("8 key L1 [1]", 0, params.getColumnPos(0));
+        assertEquals("8 key L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("8 key L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("8 key L1 [4]", 3, params.getColumnPos(3));
+        assertEquals("8 key L1 [5]", 0, params.getColumnPos(4));
+        assertEquals("8 key L1 [6]", 1, params.getColumnPos(5));
+        assertEquals("8 key L1 [7]", 2, params.getColumnPos(6));
+        assertEquals("8 key L1 [8]", 3, params.getColumnPos(7));
+        assertEquals("8 key L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("8 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___ [7] [5] [6] [8]
+    // |___ ___ [3] [1] [2] [4]
+    public void testLayout8KeyL2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(8, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L2, KEYBOARD_WIDTH);
+        assertEquals("8 key L2 columns", 4, params.mNumColumns);
+        assertEquals("8 key L2 rows", 2, params.mNumRows);
+        assertEquals("8 key L2 left", 1, params.mLeftKeys);
+        assertEquals("8 key L2 right", 3, params.mRightKeys);
+        assertEquals("8 key L2 [1]", 0, params.getColumnPos(0));
+        assertEquals("8 key L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("8 key L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("8 key L2 [4]", 2, params.getColumnPos(3));
+        assertEquals("8 key L2 [5]", 0, params.getColumnPos(4));
+        assertEquals("8 key L2 [6]", 1, params.getColumnPos(5));
+        assertEquals("8 key L2 [7]", -1, params.getColumnPos(6));
+        assertEquals("8 key L2 [8]", 2, params.getColumnPos(7));
+        assertEquals("8 key L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("8 key L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [8] [7] [6] [5]|
+    // [4] [3] [2] [1]|
+    public void testLayout8KeyR0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(8, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R0, KEYBOARD_WIDTH);
+        assertEquals("8 key R0 columns", 4, params.mNumColumns);
+        assertEquals("8 key R0 rows", 2, params.mNumRows);
+        assertEquals("8 key R0 left", 3, params.mLeftKeys);
+        assertEquals("8 key R0 right", 1, params.mRightKeys);
+        assertEquals("8 key R0 [1]", 0, params.getColumnPos(0));
+        assertEquals("8 key R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("8 key R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("8 key R0 [4]", -3, params.getColumnPos(3));
+        assertEquals("8 key R0 [5]", 0, params.getColumnPos(4));
+        assertEquals("8 key R0 [6]", -1, params.getColumnPos(5));
+        assertEquals("8 key R0 [7]", -2, params.getColumnPos(6));
+        assertEquals("8 key R0 [8]", -3, params.getColumnPos(7));
+        assertEquals("8 key R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("8 key R0 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    // [8] [7] [6] [5] ___|
+    // [4] [3] [2] [1] ___|
+    public void testLayout8KeyR1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(8, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R1, KEYBOARD_WIDTH);
+        assertEquals("8 key R1 columns", 4, params.mNumColumns);
+        assertEquals("8 key R1 rows", 2, params.mNumRows);
+        assertEquals("8 key R1 left", 3, params.mLeftKeys);
+        assertEquals("8 key R1 right", 1, params.mRightKeys);
+        assertEquals("8 key R1 [1]", 0, params.getColumnPos(0));
+        assertEquals("8 key R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("8 key R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("8 key R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("8 key R1 [5]", 0, params.getColumnPos(4));
+        assertEquals("8 key R1 [6]", -1, params.getColumnPos(5));
+        assertEquals("8 key R1 [7]", -2, params.getColumnPos(6));
+        assertEquals("8 key R1 [8]", -3, params.getColumnPos(7));
+        assertEquals("8 key R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("8 key R1 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    // [8] [7] [5] [6] ___ ___|
+    // [4] [3] [1] [2] ___ ___|
+    public void testLayout8KeyR2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(8, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R2, KEYBOARD_WIDTH);
+        assertEquals("8 key R2 columns", 4, params.mNumColumns);
+        assertEquals("8 key R2 rows", 2, params.mNumRows);
+        assertEquals("8 key R2 left", 2, params.mLeftKeys);
+        assertEquals("8 key R2 right", 2, params.mRightKeys);
+        assertEquals("8 key R2 [1]", 0, params.getColumnPos(0));
+        assertEquals("8 key R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("8 key R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("8 key R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("8 key R2 [5]", 0, params.getColumnPos(4));
+        assertEquals("8 key R2 [6]", 1, params.getColumnPos(5));
+        assertEquals("8 key R2 [7]", -1, params.getColumnPos(6));
+        assertEquals("8 key R2 [8]", -2, params.getColumnPos(7));
+        assertEquals("8 key R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("8 key R2 default", WIDTH * 2, params.getDefaultKeyCoordX());
     }
 
     //   [8] [6] [7] [9]
     // [5] [3] [1] [2] [4]
-    public void testLayout9Key() {
-        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
-                9, MAX_COLUMNS, WIDTH, HEIGHT,
-                WIDTH * 5, WIDTH * 10);
-        assertEquals("9 key columns", 5, params.mNumColumns);
-        assertEquals("9 key rows", 2, params.mNumRows);
-        assertEquals("9 key left", 2, params.mLeftKeys);
-        assertEquals("9 key right", 3, params.mRightKeys);
-        assertEquals("9 key [1]", 0, params.getColumnPos(0));
-        assertEquals("9 key [2]", 1, params.getColumnPos(1));
-        assertEquals("9 key [3]", -1, params.getColumnPos(2));
-        assertEquals("9 key [4]", 2, params.getColumnPos(3));
-        assertEquals("9 key [5]", -2, params.getColumnPos(4));
-        assertEquals("9 key [6]", 0, params.getColumnPos(5));
-        assertEquals("9 key [7]", 1, params.getColumnPos(6));
-        assertEquals("9 key [8]", -1, params.getColumnPos(7));
-        assertEquals("9 key [9]", 2, params.getColumnPos(8));
-        assertEquals("9 key centering", true, params.mTopRowNeedsCentering);
-        assertEquals("9 key default", WIDTH * 2, params.getDefaultKeyCoordX());
+    public void testLayout9KeyM0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(9, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_M0, KEYBOARD_WIDTH);
+        assertEquals("9 key M0 columns", 5, params.mNumColumns);
+        assertEquals("9 key M0 rows", 2, params.mNumRows);
+        assertEquals("9 key M0 left", 2, params.mLeftKeys);
+        assertEquals("9 key M0 right", 3, params.mRightKeys);
+        assertEquals("9 key M0 [1]", 0, params.getColumnPos(0));
+        assertEquals("9 key M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("9 key M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("9 key M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("9 key M0 [5]", -2, params.getColumnPos(4));
+        assertEquals("9 key M0 [6]", 0, params.getColumnPos(5));
+        assertEquals("9 key M0 [7]", 1, params.getColumnPos(6));
+        assertEquals("9 key M0 [8]", -1, params.getColumnPos(7));
+        assertEquals("9 key M0 [9]", 2, params.getColumnPos(8));
+        assertEquals("9 key M0 adjust", -1, params.mTopRowAdjustment);
+        assertEquals("9 key M0 default", WIDTH * 2, params.getDefaultKeyCoordX());
     }
 
-    // Nine keys test.  There is no key space for mini keyboard at left of the parent key.
-    //   [6] [7] [8] [9]
-    // [1] [2] [3] [4] [5]
-    public void testLayout9KeyLeft() {
-        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
-                9, MAX_COLUMNS, WIDTH, HEIGHT,
-                0, WIDTH * 10);
-        assertEquals("9 key left columns", 5, params.mNumColumns);
-        assertEquals("9 key left rows", 2, params.mNumRows);
-        assertEquals("9 key left left", 0, params.mLeftKeys);
-        assertEquals("9 key left right", 5, params.mRightKeys);
-        assertEquals("9 key left [1]", 0, params.getColumnPos(0));
-        assertEquals("9 key left [2]", 1, params.getColumnPos(1));
-        assertEquals("9 key left [3]", 2, params.getColumnPos(2));
-        assertEquals("9 key left [4]", 3, params.getColumnPos(3));
-        assertEquals("9 key left [5]", 4, params.getColumnPos(4));
-        assertEquals("9 key left [6]", 0, params.getColumnPos(5));
-        assertEquals("9 key left [7]", 1, params.getColumnPos(6));
-        assertEquals("9 key left [8]", 2, params.getColumnPos(7));
-        assertEquals("9 key left [9]", 3, params.getColumnPos(8));
-        assertEquals("9 key left centering", true, params.mTopRowNeedsCentering);
-        assertEquals("9 key left default", 0, params.getDefaultKeyCoordX());
+    // |[6] [7] [8] [9]
+    // |[1] [2] [3] [4] [5]
+    public void testLayout9KeyL0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(9, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L0, KEYBOARD_WIDTH);
+        assertEquals("9 key L0 columns", 5, params.mNumColumns);
+        assertEquals("9 key L0 rows", 2, params.mNumRows);
+        assertEquals("9 key L0 left", 0, params.mLeftKeys);
+        assertEquals("9 key L0 right", 5, params.mRightKeys);
+        assertEquals("9 key L0 [1]", 0, params.getColumnPos(0));
+        assertEquals("9 key L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("9 key L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("9 key L0 [4]", 3, params.getColumnPos(3));
+        assertEquals("9 key L0 [5]", 4, params.getColumnPos(4));
+        assertEquals("9 key L0 [6]", 0, params.getColumnPos(5));
+        assertEquals("9 key L0 [7]", 1, params.getColumnPos(6));
+        assertEquals("9 key L0 [8]", 2, params.getColumnPos(7));
+        assertEquals("9 key L0 [9]", 3, params.getColumnPos(8));
+        assertEquals("9 key L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("9 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
     }
 
-    // Nine keys test.  There is only one key space for mini keyboard at left of the parent key.
-    //   [8] [6] [7] [9]
-    // [3] [1] [2] [4] [5]
-    public void testLayout9KeyNearLeft() {
-        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
-                9, MAX_COLUMNS, WIDTH, HEIGHT,
-                WIDTH, WIDTH * 10);
-        assertEquals("9 key near left columns", 5, params.mNumColumns);
-        assertEquals("9 key near left rows", 2, params.mNumRows);
-        assertEquals("9 key near left left", 1, params.mLeftKeys);
-        assertEquals("9 key near left right", 4, params.mRightKeys);
-        assertEquals("9 key near left [1]", 0, params.getColumnPos(0));
-        assertEquals("9 key near left [2]", 1, params.getColumnPos(1));
-        assertEquals("9 key near left [3]", -1, params.getColumnPos(2));
-        assertEquals("9 key near left [4]", 2, params.getColumnPos(3));
-        assertEquals("9 key near left [5]", 3, params.getColumnPos(4));
-        assertEquals("9 key near left [6]", 0, params.getColumnPos(5));
-        assertEquals("9 key near left [7]", 1, params.getColumnPos(6));
-        assertEquals("9 key near left [8]", -1, params.getColumnPos(7));
-        assertEquals("9 key near left [9]", 2, params.getColumnPos(8));
-        assertEquals("9 key near left centering", true, params.mTopRowNeedsCentering);
-        assertEquals("9 key near left default", WIDTH, params.getDefaultKeyCoordX());
+    // |___ [6] [7] [8] [9]
+    // |___ [1] [2] [3] [4] [5]
+    public void testLayout9KeyL1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(9, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L1, KEYBOARD_WIDTH);
+        assertEquals("9 key L1 columns", 5, params.mNumColumns);
+        assertEquals("9 key L1 rows", 2, params.mNumRows);
+        assertEquals("9 key L1 left", 0, params.mLeftKeys);
+        assertEquals("9 key L1 right", 5, params.mRightKeys);
+        assertEquals("9 key L1 [1]", 0, params.getColumnPos(0));
+        assertEquals("9 key L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("9 key L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("9 key L1 [4]", 3, params.getColumnPos(3));
+        assertEquals("9 key L1 [5]", 4, params.getColumnPos(4));
+        assertEquals("9 key L1 [6]", 0, params.getColumnPos(5));
+        assertEquals("9 key L1 [7]", 1, params.getColumnPos(6));
+        assertEquals("9 key L1 [8]", 2, params.getColumnPos(7));
+        assertEquals("9 key L1 [9]", 3, params.getColumnPos(8));
+        assertEquals("9 key L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("9 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___   [8] [6] [7] [9]
+    // |___ ___ [3] [1] [2] [4] [5]
+    public void testLayout9KeyL2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(9, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L2, KEYBOARD_WIDTH);
+        assertEquals("9 key L2 columns", 5, params.mNumColumns);
+        assertEquals("9 key L2 rows", 2, params.mNumRows);
+        assertEquals("9 key L2 left", 1, params.mLeftKeys);
+        assertEquals("9 key L2 right", 4, params.mRightKeys);
+        assertEquals("9 key L2 [1]", 0, params.getColumnPos(0));
+        assertEquals("9 key L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("9 key L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("9 key L2 [4]", 2, params.getColumnPos(3));
+        assertEquals("9 key L2 [5]", 3, params.getColumnPos(4));
+        assertEquals("9 key L2 [6]", 0, params.getColumnPos(5));
+        assertEquals("9 key L2 [7]", 1, params.getColumnPos(6));
+        assertEquals("9 key L2 [8]", -1, params.getColumnPos(7));
+        assertEquals("9 key L2 [9]", 2, params.getColumnPos(8));
+        assertEquals("9 key L2 adjust", 1, params.mTopRowAdjustment);
+        assertEquals("9 key L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    //     [9] [8] [7] [6]|
+    // [5] [4] [3] [2] [1]|
+    public void testLayout9KeyR0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(9, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R0, KEYBOARD_WIDTH);
+        assertEquals("9 key R0 columns", 5, params.mNumColumns);
+        assertEquals("9 key R0 rows", 2, params.mNumRows);
+        assertEquals("9 key R0 left", 4, params.mLeftKeys);
+        assertEquals("9 key R0 right", 1, params.mRightKeys);
+        assertEquals("9 key R0 [1]", 0, params.getColumnPos(0));
+        assertEquals("9 key R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("9 key R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("9 key R0 [4]", -3, params.getColumnPos(3));
+        assertEquals("9 key R0 [5]", -4, params.getColumnPos(4));
+        assertEquals("9 key R0 [6]", 0, params.getColumnPos(5));
+        assertEquals("9 key R0 [7]", -1, params.getColumnPos(6));
+        assertEquals("9 key R0 [8]", -2, params.getColumnPos(7));
+        assertEquals("9 key R0 [9]", -3, params.getColumnPos(8));
+        assertEquals("9 key R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("9 key R0 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    //     [9] [8] [7] [6] ___|
+    // [5] [4] [3] [2] [1] ___|
+    public void testLayout9KeyR1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(9, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R1, KEYBOARD_WIDTH);
+        assertEquals("9 key R1 columns", 5, params.mNumColumns);
+        assertEquals("9 key R1 rows", 2, params.mNumRows);
+        assertEquals("9 key R1 left", 4, params.mLeftKeys);
+        assertEquals("9 key R1 right", 1, params.mRightKeys);
+        assertEquals("9 key R1 [1]", 0, params.getColumnPos(0));
+        assertEquals("9 key R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("9 key R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("9 key R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("9 key R1 [5]", -4, params.getColumnPos(4));
+        assertEquals("9 key R1 [6]", 0, params.getColumnPos(5));
+        assertEquals("9 key R1 [7]", -1, params.getColumnPos(6));
+        assertEquals("9 key R1 [8]", -2, params.getColumnPos(7));
+        assertEquals("9 key R1 [9]", -3, params.getColumnPos(8));
+        assertEquals("9 key R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("9 key R1 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    //   [9] [8] [6] [7]   ___ ___|
+    // [5] [4] [3] [1] [2] ___ ___|
+    public void testLayout9KeyR2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(9, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R2, KEYBOARD_WIDTH);
+        assertEquals("9 key R2 columns", 5, params.mNumColumns);
+        assertEquals("9 key R2 rows", 2, params.mNumRows);
+        assertEquals("9 key R2 left", 3, params.mLeftKeys);
+        assertEquals("9 key R2 right", 2, params.mRightKeys);
+        assertEquals("9 key R2 [1]", 0, params.getColumnPos(0));
+        assertEquals("9 key R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("9 key R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("9 key R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("9 key R2 [5]", -3, params.getColumnPos(4));
+        assertEquals("9 key R2 [6]", 0, params.getColumnPos(5));
+        assertEquals("9 key R2 [7]", 1, params.getColumnPos(6));
+        assertEquals("9 key R2 [8]", -1, params.getColumnPos(7));
+        assertEquals("9 key R2 [9]", -2, params.getColumnPos(8));
+        assertEquals("9 key R2 adjust", -1, params.mTopRowAdjustment);
+        assertEquals("9 key R2 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    // [A] [8] [6] [7] [9]
+    // [5] [3] [1] [2] [4]
+    public void testLayout10KeyM0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(10, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_M0, KEYBOARD_WIDTH);
+        assertEquals("10 key M0 columns", 5, params.mNumColumns);
+        assertEquals("10 key M0 rows", 2, params.mNumRows);
+        assertEquals("10 key M0 left", 2, params.mLeftKeys);
+        assertEquals("10 key M0 right", 3, params.mRightKeys);
+        assertEquals("10 key M0 [1]", 0, params.getColumnPos(0));
+        assertEquals("10 key M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("10 key M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("10 key M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("10 key M0 [5]", -2, params.getColumnPos(4));
+        assertEquals("10 key M0 [6]", 0, params.getColumnPos(5));
+        assertEquals("10 key M0 [7]", 1, params.getColumnPos(6));
+        assertEquals("10 key M0 [8]", -1, params.getColumnPos(7));
+        assertEquals("10 key M0 [9]", 2, params.getColumnPos(8));
+        assertEquals("10 key M0 [A]", -2, params.getColumnPos(9));
+        assertEquals("10 key M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("10 key M0 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    // |[6] [7] [8] [9] [A]
+    // |[1] [2] [3] [4] [5]
+    public void testLayout10KeyL0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(10, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L0, KEYBOARD_WIDTH);
+        assertEquals("10 key L0 columns", 5, params.mNumColumns);
+        assertEquals("10 key L0 rows", 2, params.mNumRows);
+        assertEquals("10 key L0 left", 0, params.mLeftKeys);
+        assertEquals("10 key L0 right", 5, params.mRightKeys);
+        assertEquals("10 key L0 [1]", 0, params.getColumnPos(0));
+        assertEquals("10 key L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("10 key L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("10 key L0 [4]", 3, params.getColumnPos(3));
+        assertEquals("10 key L0 [5]", 4, params.getColumnPos(4));
+        assertEquals("10 key L0 [6]", 0, params.getColumnPos(5));
+        assertEquals("10 key L0 [7]", 1, params.getColumnPos(6));
+        assertEquals("10 key L0 [8]", 2, params.getColumnPos(7));
+        assertEquals("10 key L0 [9]", 3, params.getColumnPos(8));
+        assertEquals("10 key L0 [A]", 4, params.getColumnPos(9));
+        assertEquals("10 key L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("10 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [6] [7] [8] [9] [A]
+    // |___ [1] [2] [3] [4] [5]
+    public void testLayout10KeyL1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(10, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L1, KEYBOARD_WIDTH);
+        assertEquals("10 key L1 columns", 5, params.mNumColumns);
+        assertEquals("10 key L1 rows", 2, params.mNumRows);
+        assertEquals("10 key L1 left", 0, params.mLeftKeys);
+        assertEquals("10 key L1 right", 5, params.mRightKeys);
+        assertEquals("10 key L1 [1]", 0, params.getColumnPos(0));
+        assertEquals("10 key L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("10 key L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("10 key L1 [4]", 3, params.getColumnPos(3));
+        assertEquals("10 key L1 [5]", 4, params.getColumnPos(4));
+        assertEquals("10 key L1 [6]", 0, params.getColumnPos(5));
+        assertEquals("10 key L1 [7]", 1, params.getColumnPos(6));
+        assertEquals("10 key L1 [8]", 2, params.getColumnPos(7));
+        assertEquals("10 key L1 [9]", 3, params.getColumnPos(8));
+        assertEquals("10 key L1 [A]", 4, params.getColumnPos(9));
+        assertEquals("10 key L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("10 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___ [8] [6] [7] [9] [A]
+    // |___ ___ [3] [1] [2] [4] [5]
+    public void testLayout10KeyL2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(10, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_L2, KEYBOARD_WIDTH);
+        assertEquals("10 key L2 columns", 5, params.mNumColumns);
+        assertEquals("10 key L2 rows", 2, params.mNumRows);
+        assertEquals("10 key L2 left", 1, params.mLeftKeys);
+        assertEquals("10 key L2 right", 4, params.mRightKeys);
+        assertEquals("10 key L2 [1]", 0, params.getColumnPos(0));
+        assertEquals("10 key L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("10 key L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("10 key L2 [4]", 2, params.getColumnPos(3));
+        assertEquals("10 key L2 [5]", 3, params.getColumnPos(4));
+        assertEquals("10 key L2 [6]", 0, params.getColumnPos(5));
+        assertEquals("10 key L2 [7]", 1, params.getColumnPos(6));
+        assertEquals("10 key L2 [8]", -1, params.getColumnPos(7));
+        assertEquals("10 key L2 [9]", 2, params.getColumnPos(8));
+        assertEquals("10 key L2 [A]", 3, params.getColumnPos(9));
+        assertEquals("10 key L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("10 key L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [A] [9] [8] [7] [6]|
+    // [5] [4] [3] [2] [1]|
+    public void testLayout10KeyR0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(10, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R0, KEYBOARD_WIDTH);
+        assertEquals("10 key R0 columns", 5, params.mNumColumns);
+        assertEquals("10 key R0 rows", 2, params.mNumRows);
+        assertEquals("10 key R0 left", 4, params.mLeftKeys);
+        assertEquals("10 key R0 right", 1, params.mRightKeys);
+        assertEquals("10 key R0 [1]", 0, params.getColumnPos(0));
+        assertEquals("10 key R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("10 key R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("10 key R0 [4]", -3, params.getColumnPos(3));
+        assertEquals("10 key R0 [5]", -4, params.getColumnPos(4));
+        assertEquals("10 key R0 [6]", 0, params.getColumnPos(5));
+        assertEquals("10 key R0 [7]", -1, params.getColumnPos(6));
+        assertEquals("10 key R0 [8]", -2, params.getColumnPos(7));
+        assertEquals("10 key R0 [9]", -3, params.getColumnPos(8));
+        assertEquals("10 key R0 [A]", -4, params.getColumnPos(9));
+        assertEquals("10 key R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("10 key R0 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    // [A] [9] [8] [7] [6] ___|
+    // [5] [4] [3] [2] [1] ___|
+    public void testLayout10KeyR1() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(10, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R1, KEYBOARD_WIDTH);
+        assertEquals("10 key R1 columns", 5, params.mNumColumns);
+        assertEquals("10 key R1 rows", 2, params.mNumRows);
+        assertEquals("10 key R1 left", 4, params.mLeftKeys);
+        assertEquals("10 key R1 right", 1, params.mRightKeys);
+        assertEquals("10 key R1 [1]", 0, params.getColumnPos(0));
+        assertEquals("10 key R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("10 key R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("10 key R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("10 key R1 [5]", -4, params.getColumnPos(4));
+        assertEquals("10 key R1 [6]", 0, params.getColumnPos(5));
+        assertEquals("10 key R1 [7]", -1, params.getColumnPos(6));
+        assertEquals("10 key R1 [8]", -2, params.getColumnPos(7));
+        assertEquals("10 key R1 [9]", -3, params.getColumnPos(8));
+        assertEquals("10 key R1 [A]", -4, params.getColumnPos(9));
+        assertEquals("10 key R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("10 key R1 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    // [A] [9] [8] [6] [7] ___ ___|
+    // [5] [4] [3] [1] [2] ___ ___|
+    public void testLayout10KeyR2() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(10, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_R2, KEYBOARD_WIDTH);
+        assertEquals("10 key R2 columns", 5, params.mNumColumns);
+        assertEquals("10 key R2 rows", 2, params.mNumRows);
+        assertEquals("10 key R2 left", 3, params.mLeftKeys);
+        assertEquals("10 key R2 right", 2, params.mRightKeys);
+        assertEquals("10 key R2 [1]", 0, params.getColumnPos(0));
+        assertEquals("10 key R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("10 key R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("10 key R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("10 key R2 [5]", -3, params.getColumnPos(4));
+        assertEquals("10 key R2 [6]", 0, params.getColumnPos(5));
+        assertEquals("10 key R2 [7]", 1, params.getColumnPos(6));
+        assertEquals("10 key R2 [8]", -1, params.getColumnPos(7));
+        assertEquals("10 key R2 [9]", -2, params.getColumnPos(8));
+        assertEquals("10 key R2 [A]", -3, params.getColumnPos(9));
+        assertEquals("10 key R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("10 key R2 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    //   [B] [9] [A]
+    // [7] [5] [6] [8]
+    // [3] [1] [2] [4]
+    public void testLayout11KeyM0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(11, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_M0, KEYBOARD_WIDTH);
+        assertEquals("11 key M0 columns", 4, params.mNumColumns);
+        assertEquals("11 key M0 rows", 3, params.mNumRows);
+        assertEquals("11 key M0 left", 1, params.mLeftKeys);
+        assertEquals("11 key M0 right", 3, params.mRightKeys);
+        assertEquals("11 key M0 [1]", 0, params.getColumnPos(0));
+        assertEquals("11 key M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("11 key M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("11 key M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("11 key M0 [5]", 0, params.getColumnPos(4));
+        assertEquals("11 key M0 [6]", 1, params.getColumnPos(5));
+        assertEquals("11 key M0 [7]", -1, params.getColumnPos(6));
+        assertEquals("11 key M0 [8]", 2, params.getColumnPos(7));
+        assertEquals("11 key M0 [9]", 0, params.getColumnPos(8));
+        assertEquals("11 key M0 [A]", 1, params.getColumnPos(9));
+        assertEquals("11 key M0 [B]", -1, params.getColumnPos(10));
+        assertEquals("11 key M0 adjust", 1, params.mTopRowAdjustment);
+        assertEquals("11 key M0 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [B] [9] [A] [C]
+    // [7] [5] [6] [8]
+    // [3] [1] [2] [4]
+    public void testLayout12KeyM0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(12, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_M0, KEYBOARD_WIDTH);
+        assertEquals("12 key M0 columns", 4, params.mNumColumns);
+        assertEquals("12 key M0 rows", 3, params.mNumRows);
+        assertEquals("12 key M0 left", 1, params.mLeftKeys);
+        assertEquals("12 key M0 right", 3, params.mRightKeys);
+        assertEquals("12 key M0 [1]", 0, params.getColumnPos(0));
+        assertEquals("12 key M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("12 key M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("12 key M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("12 key M0 [5]", 0, params.getColumnPos(4));
+        assertEquals("12 key M0 [6]", 1, params.getColumnPos(5));
+        assertEquals("12 key M0 [7]", -1, params.getColumnPos(6));
+        assertEquals("12 key M0 [8]", 2, params.getColumnPos(7));
+        assertEquals("12 key M0 [9]", 0, params.getColumnPos(8));
+        assertEquals("12 key M0 [A]", 1, params.getColumnPos(9));
+        assertEquals("12 key M0 [B]", -1, params.getColumnPos(10));
+        assertEquals("12 key M0 [C]", 2, params.getColumnPos(11));
+        assertEquals("12 key M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("12 key M0 default", WIDTH * 1, params.getDefaultKeyCoordX());
     }
 
 
-    // Nine keys test.  There is no key space for mini keyboard at right of the parent key.
-    //   [9] [8] [7] [6]
-    // [5] [4] [3] [2] [1]
-    public void testLayout9KeyRight() {
-        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
-                9, MAX_COLUMNS, WIDTH, HEIGHT,
-                WIDTH * 9, WIDTH * 10);
-        assertEquals("9 key right columns", 5, params.mNumColumns);
-        assertEquals("9 key right rows", 2, params.mNumRows);
-        assertEquals("9 key right left", 4, params.mLeftKeys);
-        assertEquals("9 key right right", 1, params.mRightKeys);
-        assertEquals("9 key right [1]", 0, params.getColumnPos(0));
-        assertEquals("9 key right [2]", -1, params.getColumnPos(1));
-        assertEquals("9 key right [3]", -2, params.getColumnPos(2));
-        assertEquals("9 key right [4]", -3, params.getColumnPos(3));
-        assertEquals("9 key right [5]", -4, params.getColumnPos(4));
-        assertEquals("9 key right [6]", 0, params.getColumnPos(5));
-        assertEquals("9 key right [7]", -1, params.getColumnPos(6));
-        assertEquals("9 key right [8]", -2, params.getColumnPos(7));
-        assertEquals("9 key right [9]", -3, params.getColumnPos(8));
-        assertEquals("9 key right centering", true, params.mTopRowNeedsCentering);
-        assertEquals("9 key right default", WIDTH * 4, params.getDefaultKeyCoordX());
-    }
-
-    // Nine keys test.  There is only one key space for mini keyboard at right of the parent key.
-    //   [9] [8] [6] [7]
-    // [5] [4] [3] [1] [2]
-    public void testLayout9KeyNearRight() {
-        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
-                9, MAX_COLUMNS, WIDTH, HEIGHT,
-                WIDTH * 8, WIDTH * 10);
-        assertEquals("9 key near right columns", 5, params.mNumColumns);
-        assertEquals("9 key near right rows", 2, params.mNumRows);
-        assertEquals("9 key near right left", 3, params.mLeftKeys);
-        assertEquals("9 key near right right", 2, params.mRightKeys);
-        assertEquals("9 key near right [1]", 0, params.getColumnPos(0));
-        assertEquals("9 key near right [2]", 1, params.getColumnPos(1));
-        assertEquals("9 key near right [3]", -1, params.getColumnPos(2));
-        assertEquals("9 key near right [4]", -2, params.getColumnPos(3));
-        assertEquals("9 key near right [5]", -3, params.getColumnPos(4));
-        assertEquals("9 key near right [6]", 0, params.getColumnPos(5));
-        assertEquals("9 key near right [7]", 1, params.getColumnPos(6));
-        assertEquals("9 key near right [8]", -1, params.getColumnPos(7));
-        assertEquals("9 key near right [9]", -2, params.getColumnPos(8));
-        assertEquals("9 key near right centering", true, params.mTopRowNeedsCentering);
-        assertEquals("9 key near right default", WIDTH * 3, params.getDefaultKeyCoordX());
+    //     [D] [B] [C]
+    // [A] [8] [6] [7] [9]
+    // [5] [3] [1] [2] [4]
+    public void testLayout13KeyM0() {
+        MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(13, MAX_COLUMNS, WIDTH,
+                HEIGHT, XPOS_M0, KEYBOARD_WIDTH);
+        assertEquals("13 key M0 columns", 5, params.mNumColumns);
+        assertEquals("13 key M0 rows", 3, params.mNumRows);
+        assertEquals("13 key M0 left", 2, params.mLeftKeys);
+        assertEquals("13 key M0 right", 3, params.mRightKeys);
+        assertEquals("13 key M0 [1]", 0, params.getColumnPos(0));
+        assertEquals("13 key M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("13 key M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("13 key M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("13 key M0 [5]", -2, params.getColumnPos(4));
+        assertEquals("13 key M0 [6]", 0, params.getColumnPos(5));
+        assertEquals("13 key M0 [7]", 1, params.getColumnPos(6));
+        assertEquals("13 key M0 [8]", -1, params.getColumnPos(7));
+        assertEquals("13 key M0 [9]", 2, params.getColumnPos(8));
+        assertEquals("13 key M0 [A]", -2, params.getColumnPos(9));
+        assertEquals("13 key M0 [B]", 0, params.getColumnPos(10));
+        assertEquals("13 key M0 [C]", 1, params.getColumnPos(11));
+        assertEquals("13 key M0 [D]", -1, params.getColumnPos(12));
+        assertEquals("13 key M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("13 key M0 default", WIDTH * 2, params.getDefaultKeyCoordX());
     }
 }
diff --git a/tests/src/com/android/inputmethod/latin/SuggestHelper.java b/tests/src/com/android/inputmethod/latin/SuggestHelper.java
index 1d0a5b7..5d1ab70 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestHelper.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestHelper.java
@@ -55,7 +55,7 @@
         mSuggest.setCorrectionMode(Suggest.CORRECTION_FULL);
         mKeyDetector.setKeyboard(mKeyboard, 0, 0);
         mKeyDetector.setProximityCorrectionEnabled(true);
-        mKeyDetector.setProximityThreshold(KeyDetector.getMostCommonKeyWidth(mKeyboard));
+        mKeyDetector.setProximityThreshold(mKeyboard.getMostCommonKeyWidth());
     }
 
     public void setCorrectionMode(int correctionMode) {