Fix 5335993, calculate correct size of lockscreen buttons

The buttons on the lockscreen were sized at startup time,
before the actual size of the keyboard's container (KeyboardView)
was known. Also, horizontal/vertical gaps were not taken into
account in calculating perecent sizes of the keys. This change
causes resize events (including the first one where the container
size is finally known) to recalculate the keys' sizes and positions
according to correct sizing of the container and the keyboard's gaps.

Change-Id: I5ba7a401226ed4b100e5739f3405388955d97997
diff --git a/core/java/android/inputmethodservice/Keyboard.java b/core/java/android/inputmethodservice/Keyboard.java
index 10386f8..4fe54c0 100644
--- a/core/java/android/inputmethodservice/Keyboard.java
+++ b/core/java/android/inputmethodservice/Keyboard.java
@@ -144,6 +144,8 @@
     /** Number of key widths from current touch point to search for nearest keys. */
     private static float SEARCH_DISTANCE = 1.8f;
 
+    private ArrayList<Row> rows = new ArrayList<Row>();
+
     /**
      * Container for keys in the keyboard. All keys in a row are at the same Y-coordinate. 
      * Some of the key size defaults can be overridden per row from what the {@link Keyboard}
@@ -164,6 +166,9 @@
         public int defaultHorizontalGap;
         /** Vertical gap following this row. */
         public int verticalGap;
+
+        ArrayList<Key> mKeys = new ArrayList<Key>();
+
         /**
          * Edge flags for this row of keys. Possible values that can be assigned are
          * {@link Keyboard#EDGE_TOP EDGE_TOP} and {@link Keyboard#EDGE_BOTTOM EDGE_BOTTOM}  
@@ -256,7 +261,7 @@
         public CharSequence text;
         /** Popup characters */
         public CharSequence popupCharacters;
-        
+
         /** 
          * Flags that specify the anchoring to edges of the keyboard for detecting touch events
          * that are just out of the boundary of the key. This is a bit mask of 
@@ -596,11 +601,44 @@
             column++;
             x += key.width + key.gap;
             mKeys.add(key);
+            row.mKeys.add(key);
             if (x > mTotalWidth) {
                 mTotalWidth = x;
             }
         }
-        mTotalHeight = y + mDefaultHeight; 
+        mTotalHeight = y + mDefaultHeight;
+        rows.add(row);
+    }
+
+    final void resize(int newWidth, int newHeight) {
+        int numRows = rows.size();
+        for (int rowIndex = 0; rowIndex < numRows; ++rowIndex) {
+            Row row = rows.get(rowIndex);
+            int numKeys = row.mKeys.size();
+            int totalGap = 0;
+            int totalWidth = 0;
+            for (int keyIndex = 0; keyIndex < numKeys; ++keyIndex) {
+                Key key = row.mKeys.get(keyIndex);
+                if (keyIndex > 0) {
+                    totalGap += key.gap;
+                }
+                totalWidth += key.width;
+            }
+            if (totalGap + totalWidth > newWidth) {
+                int x = 0;
+                float scaleFactor = (float)(newWidth - totalGap) / totalWidth;
+                for (int keyIndex = 0; keyIndex < numKeys; ++keyIndex) {
+                    Key key = row.mKeys.get(keyIndex);
+                    key.width *= scaleFactor;
+                    key.x = x;
+                    x += key.width + key.gap;
+                }
+            }
+        }
+        mTotalWidth = newWidth;
+        // TODO: This does not adjust the vertical placement according to the new size.
+        // The main problem in the previous code was horizontal placement/size, but we should
+        // also recalculate the vertical sizes/positions when we get this resize call.
     }
     
     public List<Key> getKeys() {
@@ -749,7 +787,7 @@
         Row currentRow = null;
         Resources res = context.getResources();
         boolean skipRow = false;
-        
+
         try {
             int event;
             while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
@@ -759,6 +797,7 @@
                         inRow = true;
                         x = 0;
                         currentRow = createRowFromXml(res, parser);
+                        rows.add(currentRow);
                         skipRow = currentRow.mode != 0 && currentRow.mode != mKeyboardMode;
                         if (skipRow) {
                             skipToEndOfRow(parser);
@@ -781,6 +820,7 @@
                         } else if (key.codes[0] == KEYCODE_ALT) {
                             mModifierKeys.add(key);
                         }
+                        currentRow.mKeys.add(key);
                     } else if (TAG_KEYBOARD.equals(tag)) {
                         parseKeyboardAttributes(res, parser);
                     }
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index 05444f6..1119c1e 100644
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -376,6 +376,7 @@
         initGestureDetector();
     }
 
+
     private void initGestureDetector() {
         mGestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
             @Override
@@ -615,6 +616,9 @@
     @Override
     public void onSizeChanged(int w, int h, int oldw, int oldh) {
         super.onSizeChanged(w, h, oldw, oldh);
+        if (mKeyboard != null) {
+            mKeyboard.resize(w, h);
+        }
         // Release the buffer, if any and it will be reallocated on the next draw
         mBuffer = null;
     }
diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index 694db50..3343d8b 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -170,6 +170,7 @@
     <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
         android:layout_width="270dip"
         android:layout_height="wrap_content"
+        android:layout_marginLeft="4dip"
         android:layout_marginRight="4dip"
         android:background="#40000000"
         android:layout_marginTop="5dip"
diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml
index 27a51da..2a66d7d 100644
--- a/core/res/res/layout/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_password_portrait.xml
@@ -132,7 +132,7 @@
     <!-- Numeric keyboard -->
     <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
+        android:layout_marginLeft="4dip"
         android:layout_marginRight="4dip"
         android:paddingTop="4dip"
         android:paddingBottom="4dip"