Merge "Remove redandant key from popup mini keyboard which has settings key"
diff --git a/java/res/drawable-hdpi/sym_keyboard_voice_off_holo.png b/java/res/drawable-hdpi/sym_keyboard_voice_off_holo.png
index 8a445eb..6e6279a 100644
--- a/java/res/drawable-hdpi/sym_keyboard_voice_off_holo.png
+++ b/java/res/drawable-hdpi/sym_keyboard_voice_off_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_voice_off_holo.png b/java/res/drawable-mdpi/sym_keyboard_voice_off_holo.png
index 081a130..44919df 100644
--- a/java/res/drawable-mdpi/sym_keyboard_voice_off_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_voice_off_holo.png
Binary files differ
diff --git a/java/res/layout/input_basic.xml b/java/res/layout/input_basic.xml
index 7b85bae..86ae82d 100644
--- a/java/res/layout/input_basic.xml
+++ b/java/res/layout/input_basic.xml
@@ -25,6 +25,7 @@
         android:layout_alignParentBottom="true"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:padding="0dip"
         android:background="@drawable/keyboard_background"
 
         latin:keyBackground="@drawable/btn_keyboard_key"
diff --git a/java/res/layout/input_basic_highcontrast.xml b/java/res/layout/input_basic_highcontrast.xml
index d9200fd..03b22ef 100644
--- a/java/res/layout/input_basic_highcontrast.xml
+++ b/java/res/layout/input_basic_highcontrast.xml
@@ -21,11 +21,11 @@
 <com.android.inputmethod.keyboard.LatinKeyboardView
         xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
-
         android:id="@+id/LatinkeyboardBaseView"
         android:layout_alignParentBottom="true"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:padding="0dip"
         android:background="@android:color/black"
 
         latin:keyBackground="@drawable/btn_keyboard_key3"
diff --git a/java/res/layout/input_gingerbread.xml b/java/res/layout/input_gingerbread.xml
index 6233e6d..9332f9d 100644
--- a/java/res/layout/input_gingerbread.xml
+++ b/java/res/layout/input_gingerbread.xml
@@ -25,8 +25,7 @@
         android:layout_alignParentBottom="true"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:paddingTop="@dimen/keyboard_top_padding"
-        android:paddingBottom="@dimen/keyboard_bottom_padding"
+        android:padding="0dip"
         android:background="@drawable/keyboard_dark_background"
 
         latin:keyBackground="@drawable/btn_keyboard_key_gingerbread"
diff --git a/java/res/layout/input_honeycomb.xml b/java/res/layout/input_honeycomb.xml
index 96b10b7..42bedb4 100644
--- a/java/res/layout/input_honeycomb.xml
+++ b/java/res/layout/input_honeycomb.xml
@@ -25,8 +25,7 @@
         android:layout_alignParentBottom="true"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:paddingTop="@dimen/keyboard_top_padding"
-        android:paddingBottom="@dimen/keyboard_bottom_padding"
+        android:padding="0dip"
         android:background="@drawable/keyboard_background_holo"
 
         latin:keyBackground="@drawable/btn_keyboard_key_honeycomb"
diff --git a/java/res/layout/input_stone_bold.xml b/java/res/layout/input_stone_bold.xml
index 6fdc938..22ac14e 100644
--- a/java/res/layout/input_stone_bold.xml
+++ b/java/res/layout/input_stone_bold.xml
@@ -25,6 +25,7 @@
         android:layout_alignParentBottom="true"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:padding="0dip"
         android:background="@drawable/keyboard_background"
 
         latin:keyBackground="@drawable/btn_keyboard_key_stone"
@@ -33,5 +34,5 @@
         latin:shadowColor="@color/latinkeyboard_key_color_white"
         latin:keyLetterStyle="bold"
         latin:colorScheme="black"
-        latin:popupLayout="@layout/input_stone_popup"
+        latin:popupLayout="@layout/keyboard_popup_stone"
         />
diff --git a/java/res/layout/input_stone_normal.xml b/java/res/layout/input_stone_normal.xml
index 6ae9aed..8baecab 100644
--- a/java/res/layout/input_stone_normal.xml
+++ b/java/res/layout/input_stone_normal.xml
@@ -25,6 +25,7 @@
         android:layout_alignParentBottom="true"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:padding="0dip"
         android:background="@drawable/keyboard_background"
 
         latin:keyBackground="@drawable/btn_keyboard_key_stone"
@@ -32,5 +33,5 @@
         latin:keyTextColorDisabled="#FF808080"
         latin:shadowColor="@color/latinkeyboard_key_color_white"
         latin:colorScheme="black"
-        latin:popupLayout="@layout/input_stone_popup"
+        latin:popupLayout="@layout/keyboard_popup_stone"
         />
diff --git a/java/res/layout/input_stone_popup.xml b/java/res/layout/keyboard_popup_stone.xml
similarity index 96%
rename from java/res/layout/input_stone_popup.xml
rename to java/res/layout/keyboard_popup_stone.xml
index b4da045..e6acee3 100644
--- a/java/res/layout/input_stone_popup.xml
+++ b/java/res/layout/keyboard_popup_stone.xml
@@ -36,6 +36,5 @@
             latin:keyBackground="@drawable/btn_keyboard_key_stone"
             latin:keyTextColor="@color/latinkeyboard_key_color_black"
             latin:shadowColor="@color/latinkeyboard_key_color_white"
-            latin:popupLayout="@layout/input_stone_popup"
         />
 </LinearLayout>
diff --git a/java/res/values-land/dimens.xml b/java/res/values-land/dimens.xml
index 7df124b..6954ba2 100644
--- a/java/res/values-land/dimens.xml
+++ b/java/res/values-land/dimens.xml
@@ -27,6 +27,7 @@
     <dimen name="popup_key_height">0.270in</dimen>
     <dimen name="keyboard_top_padding">0.0in</dimen>
     <dimen name="keyboard_bottom_padding">0.0in</dimen>
+    <dimen name="keyboard_horizontal_edges_padding">0.0in</dimen>
     <dimen name="candidate_strip_height">38dip</dimen>
     <dimen name="candidate_strip_fading_edge_length">63dip</dimen>
     <dimen name="spacebar_vertical_correction">2dip</dimen>
diff --git a/java/res/values-xlarge-land/dimens.xml b/java/res/values-xlarge-land/dimens.xml
index ba42ddd..fd6b1f3 100644
--- a/java/res/values-xlarge-land/dimens.xml
+++ b/java/res/values-xlarge-land/dimens.xml
@@ -28,6 +28,7 @@
     <dimen name="popup_key_height">13.0mm</dimen>
     <dimen name="keyboard_top_padding">1.1mm</dimen>
     <dimen name="keyboard_bottom_padding">0.0mm</dimen>
+    <dimen name="keyboard_horizontal_edges_padding">0.0mm</dimen>
 
     <dimen name="key_letter_size">28dip</dimen>
     <dimen name="key_label_text_size">20dip</dimen>
diff --git a/java/res/values-xlarge/dimens.xml b/java/res/values-xlarge/dimens.xml
index cdb6e89..0dc5621 100644
--- a/java/res/values-xlarge/dimens.xml
+++ b/java/res/values-xlarge/dimens.xml
@@ -28,6 +28,7 @@
     <dimen name="popup_key_height">10.0mm</dimen>
     <dimen name="keyboard_top_padding">1.1mm</dimen>
     <dimen name="keyboard_bottom_padding">0.0mm</dimen>
+    <dimen name="keyboard_horizontal_edges_padding">0.0mm</dimen>
     <dimen name="mini_keyboard_horizontal_padding_holo">40dip</dimen>
     <dimen name="mini_keyboard_key_horizontal_padding">12dip</dimen>
     <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. -->
diff --git a/java/res/values/dimens.xml b/java/res/values/dimens.xml
index 2cfc17d..767dc4a 100644
--- a/java/res/values/dimens.xml
+++ b/java/res/values/dimens.xml
@@ -28,6 +28,7 @@
     <dimen name="popup_key_height">0.325in</dimen>
     <dimen name="keyboard_top_padding">0.00in</dimen>
     <dimen name="keyboard_bottom_padding">0.06in</dimen>
+    <dimen name="keyboard_horizontal_edges_padding">0.0in</dimen>
     <dimen name="mini_keyboard_horizontal_padding">16dip</dimen>
     <dimen name="mini_keyboard_horizontal_padding_holo">32dip</dimen>
     <dimen name="mini_keyboard_key_horizontal_padding">8dip</dimen>
diff --git a/java/res/xml/kbd_qwerty_row3.xml b/java/res/xml/kbd_qwerty_row3.xml
index 26608fd..27016af 100644
--- a/java/res/xml/kbd_qwerty_row3.xml
+++ b/java/res/xml/kbd_qwerty_row3.xml
@@ -26,8 +26,10 @@
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="15%p"
+            latin:keyWidth="13%p"
             latin:keyEdgeFlags="left" />
+        <Spacer
+            latin:horizontalGap="2%p" />
         <Key
             latin:keyLabel="z"
             latin:popupCharacters="@string/alternates_for_z" />
@@ -46,9 +48,11 @@
             latin:popupCharacters="@string/alternates_for_n" />
         <Key
             latin:keyLabel="m" />
+        <Spacer
+            latin:horizontalGap="2%p" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="15%p"
+            latin:keyWidth="13%p"
             latin:keyEdgeFlags="right" />
     </Row>
 </merge>
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index f578bd6..59c132e 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -379,7 +379,7 @@
      * @see android.graphics.drawable.StateListDrawable#setState(int[])
      */
     public int[] getCurrentDrawableState() {
-        final boolean pressed = mEnabled && mPressed;
+        final boolean pressed = mPressed;
         if (!mSticky && mFunctional) {
             if (pressed) {
                 return KEY_STATE_FUNCTIONAL_PRESSED;
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 4181882..f720334 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -165,7 +165,9 @@
         GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
         GRID_SIZE = GRID_WIDTH * GRID_HEIGHT;
 
-        mDisplayWidth = width;
+        final int horizontalEdgesPadding = (int)res.getDimension(
+                R.dimen.keyboard_horizontal_edges_padding);
+        mDisplayWidth = width - horizontalEdgesPadding * 2;
         mDisplayHeight = height;
 
         mDefaultHorizontalGap = 0;
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardParser.java b/java/src/com/android/inputmethod/keyboard/KeyboardParser.java
index 62e6f30..9c556c3 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardParser.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardParser.java
@@ -122,6 +122,7 @@
     private final Keyboard mKeyboard;
     private final Resources mResources;
 
+    private int mHorizontalEdgesPadding;
     private int mCurrentX = 0;
     private int mCurrentY = 0;
     private int mMaxRowWidth = 0;
@@ -132,6 +133,7 @@
     public KeyboardParser(Keyboard keyboard, Resources res) {
         mKeyboard = keyboard;
         mResources = res;
+        mHorizontalEdgesPadding = (int)res.getDimension(R.dimen.keyboard_horizontal_edges_padding);
     }
 
     public int getMaxRowWidth() {
@@ -151,6 +153,7 @@
                 final String tag = parser.getName();
                 if (TAG_KEYBOARD.equals(tag)) {
                     parseKeyboardAttributes(parser);
+                    startKeyboard();
                     parseKeyboardContent(parser, mKeyboard.getKeys());
                     break;
                 } else {
@@ -520,25 +523,32 @@
         throw new NonEmptyTag(tag, parser);
     }
 
+    private void startKeyboard() {
+        mCurrentY += (int)mResources.getDimension(R.dimen.keyboard_top_padding);
+    }
+
     private void startRow(Row row) {
         mCurrentX = 0;
+        setSpacer(mHorizontalEdgesPadding);
         mCurrentRow = row;
     }
 
     private void endRow() {
         if (mCurrentRow == null)
             throw new InflateException("orphant end row tag");
+        setSpacer(mHorizontalEdgesPadding);
+        if (mCurrentX > mMaxRowWidth)
+            mMaxRowWidth = mCurrentX;
         mCurrentY += mCurrentRow.mDefaultHeight;
         mCurrentRow = null;
     }
 
     private void endKey(Key key) {
         mCurrentX += key.mGap + key.mWidth;
-        if (mCurrentX > mMaxRowWidth)
-            mMaxRowWidth = mCurrentX;
     }
 
     private void endKeyboard(int defaultVerticalGap) {
+        mCurrentY += (int)mResources.getDimension(R.dimen.keyboard_bottom_padding);
         mTotalHeight = mCurrentY - defaultVerticalGap;
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index cc14589..e82796b 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -1056,7 +1056,7 @@
         mKeyboardActionListener.onCodeInput(Keyboard.CODE_CAPSLOCK, null, 0, 0);
     }
 
-    private void onDoubleTapShiftKey(PointerTracker tracker) {
+    private void onDoubleTapShiftKey(@SuppressWarnings("unused") PointerTracker tracker) {
         // When shift key is double tapped, the first tap is correctly processed as usual tap. And
         // the second tap is treated as this double tap event, so that we need not mark tracker
         // calling setAlreadyProcessed() nor remove the tracker from mPointerQueueueue.
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index c281970..eb5335f 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -546,6 +546,9 @@
     }
 
     private void showKeyPreviewAndUpdateKeyGraphics(int keyIndex) {
+        final Key key = getKey(keyIndex);
+        if (key != null && !key.mEnabled)
+            return;
         updateKeyGraphics(keyIndex);
         // The modifier key, such as shift key, should not be shown as preview when multi-touch is
         // supported. On the other hand, if multi-touch is not supported, the modifier key should
@@ -565,6 +568,8 @@
             return;
         }
         Key key = getKey(keyIndex);
+        if (!key.mEnabled)
+            return;
         if (key.mCode == Keyboard.CODE_SHIFT) {
             mHandler.startLongPressShiftTimer(mLongPressShiftKeyTimeout, keyIndex, this);
         } else if (key.mManualTemporaryUpperCaseCode != Keyboard.CODE_DUMMY
diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
index d87fbce..be2c6b2 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
@@ -32,12 +32,14 @@
      */
     protected static final int MAX_WORD_LENGTH = 32;
 
+    // Bigram frequency is a fixed point number with 1 meaning 1.2 and 255 meaning 1.8.
+    protected static final int BIGRAM_MAX_FREQUENCY = 255;
+
     private Context mContext;
     private char[] mWordBuilder = new char[MAX_WORD_LENGTH];
     private int mDicTypeId;
     private int mMaxDepth;
     private int mInputLength;
-    private StringBuilder sb = new StringBuilder(MAX_WORD_LENGTH);
 
     private static final char QUOTE = '\'';
 
@@ -98,6 +100,7 @@
 
         public int addFrequency(int add) {
             mFrequency += add;
+            if (mFrequency > BIGRAM_MAX_FREQUENCY) mFrequency = BIGRAM_MAX_FREQUENCY;
             return mFrequency;
         }
     }
@@ -462,6 +465,9 @@
         }
     }
 
+    // Local to reverseLookUp, but do not allocate each time.
+    private final char[] mLookedUpString = new char[MAX_WORD_LENGTH];
+
     /**
      * reverseLookUp retrieves the full word given a list of terminal nodes and adds those words
      * through callback.
@@ -474,18 +480,15 @@
         for (NextWord nextWord : terminalNodes) {
             node = nextWord.mWord;
             freq = nextWord.getFrequency();
-            // TODO Not the best way to limit suggestion threshold
-            if (freq >= UserBigramDictionary.SUGGEST_THRESHOLD) {
-                sb.setLength(0);
-                do {
-                    sb.insert(0, node.mCode);
-                    node = node.mParent;
-                } while(node != null);
+            int index = MAX_WORD_LENGTH;
+            do {
+                --index;
+                mLookedUpString[index] = node.mCode;
+                node = node.mParent;
+            } while (node != null);
 
-                // TODO better way to feed char array?
-                callback.addWord(sb.toString().toCharArray(), 0, sb.length(), freq, mDicTypeId,
-                        DataType.BIGRAM);
-            }
+            callback.addWord(mLookedUpString, index, MAX_WORD_LENGTH - index, freq, mDicTypeId,
+                    DataType.BIGRAM);
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/UserBigramDictionary.java b/java/src/com/android/inputmethod/latin/UserBigramDictionary.java
index 4750fb9..bb6642c 100644
--- a/java/src/com/android/inputmethod/latin/UserBigramDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBigramDictionary.java
@@ -44,12 +44,6 @@
     /** Maximum frequency for all pairs */
     private static final int FREQUENCY_MAX = 127;
 
-    /**
-     * If this pair is typed 6 times, it would be suggested.
-     * Should be smaller than ContactsDictionary.FREQUENCY_FOR_CONTACTS_BIGRAM
-     */
-    protected static final int SUGGEST_THRESHOLD = 6 * FREQUENCY_FOR_TYPED;
-
     /** Maximum number of pairs. Pruning will start when databases goes above this number. */
     private static int sMaxUserBigrams = 10000;