Merge "Add a number alternation to English popup mini keyboard" into gingerbread
diff --git a/java/src/com/android/inputmethod/latin/KeyDetector.java b/java/src/com/android/inputmethod/latin/KeyDetector.java
index 11d5f86..e443f27 100644
--- a/java/src/com/android/inputmethod/latin/KeyDetector.java
+++ b/java/src/com/android/inputmethod/latin/KeyDetector.java
@@ -19,18 +19,23 @@
 import android.inputmethodservice.Keyboard;
 import android.inputmethodservice.Keyboard.Key;
 
+import java.util.Arrays;
 import java.util.List;
 
 abstract class KeyDetector {
     protected Keyboard mKeyboard;
-    protected Key[] mKeys;
+    private Key[] mKeys;
 
+    protected int mCorrectionX;
+    protected int mCorrectionY;
     protected boolean mProximityCorrectOn;
     protected int mProximityThresholdSquare;
 
-    public Key[] setKeyboard(Keyboard keyboard) {
+    public Key[] setKeyboard(Keyboard keyboard, float correctionX, float correctionY) {
         if (keyboard == null)
             throw new NullPointerException();
+        mCorrectionX = (int)correctionX;
+        mCorrectionY = (int)correctionY;
         mKeyboard = keyboard;
         List<Key> keys = mKeyboard.getKeys();
         Key[] array = keys.toArray(new Key[keys.size()]);
@@ -38,6 +43,21 @@
         return array;
     }
 
+    protected int getTouchX(int x) {
+        return x + mCorrectionX;
+    }
+
+    protected int getTouchY(int y) {
+        return y + mCorrectionY;
+    }
+
+    protected Key[] getKeys() {
+        if (mKeys == null)
+            throw new IllegalStateException("keyboard isn't set");
+        // mKeyboard is guaranteed not null at setKeybaord() method
+        return mKeys;
+    }
+
     public void setProximityCorrectionEnabled(boolean enabled) {
         mProximityCorrectOn = enabled;
     }
@@ -50,7 +70,13 @@
         mProximityThresholdSquare = threshold * threshold;
     }
 
-    abstract public int[] newCodeArray();
+    public int[] newCodeArray() {
+        int[] codes = new int[getMaxNearbyKeys()];
+        Arrays.fill(codes, LatinKeyboardBaseView.NOT_A_KEY);
+        return codes;
+    }
+
+    abstract protected int getMaxNearbyKeys();
 
     abstract public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys);
 }
\ No newline at end of file
diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java
index 14b8143..48cccea 100644
--- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java
+++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java
@@ -165,7 +165,7 @@
     private float mShadowRadius;
     private Drawable mKeyBackground;
     private float mBackgroundDimAmount;
-    private int mVerticalCorrection;
+    private float mVerticalCorrection;
     private int mPreviewOffset;
     private int mPreviewHeight;
     private int mPopupLayout;
@@ -541,7 +541,8 @@
         mHandler.cancelPopupPreview();
         mKeyboard = keyboard;
         LatinImeLogger.onSetKeyboard(keyboard);
-        mKeys = mKeyDetector.setKeyboard(keyboard);
+        mKeys = mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
+                -getPaddingTop() + mVerticalCorrection);
         for (PointerTracker tracker : mPointerTrackers) {
             tracker.setKeyboard(mKeys, mDebounceHysteresis);
         }
@@ -613,9 +614,6 @@
         return mSymbolColorScheme;
     }
 
-    public void setVerticalCorrection(int verticalOffset) {
-    }
-
     public void setPopupParent(View v) {
         mPopupParent = v;
     }
@@ -1070,14 +1068,6 @@
         return mMiniKeyboardOnScreen;
     }
 
-    private int getTouchX(float x) {
-        return (int)x - getPaddingLeft();
-    }
-
-    private int getTouchY(float y) {
-        return (int)y + mVerticalCorrection - getPaddingTop();
-    }
-
     private PointerTracker getPointerTracker(final int id) {
         final ArrayList<PointerTracker> pointers = mPointerTrackers;
         final Key[] keys = mKeys;
@@ -1132,29 +1122,29 @@
 
         if (action == MotionEvent.ACTION_MOVE) {
             for (int index = 0; index < pointerCount; index++) {
-                int touchX = getTouchX(me.getX(index));
-                int touchY = getTouchY(me.getY(index));
+                int x = (int)me.getX(index);
+                int y = (int)me.getY(index);
                 int id = me.getPointerId(index);
                 PointerTracker tracker = getPointerTracker(id);
-                tracker.onMoveEvent(touchX, touchY, eventTime);
+                tracker.onMoveEvent(x, y, eventTime);
             }
         } else {
             int index = me.getActionIndex();
-            int touchX = getTouchX(me.getX(index));
-            int touchY = getTouchY(me.getY(index));
+            int x = (int)me.getX(index);
+            int y = (int)me.getY(index);
             int id = me.getPointerId(index);
             PointerTracker tracker = getPointerTracker(id);
             switch (action) {
             case MotionEvent.ACTION_DOWN:
             case MotionEvent.ACTION_POINTER_DOWN:
-                onDownEvent(tracker, touchX, touchY, eventTime);
+                onDownEvent(tracker, x, y, eventTime);
                 break;
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_POINTER_UP:
-                onUpEvent(tracker, touchX, touchY, eventTime);
+                onUpEvent(tracker, x, y, eventTime);
                 break;
             case MotionEvent.ACTION_CANCEL:
-                onCancelEvent(tracker, touchX, touchY, eventTime);
+                onCancelEvent(tracker, x, y, eventTime);
                 break;
             }
         }
@@ -1162,12 +1152,12 @@
         return true;
     }
 
-    private void onDownEvent(PointerTracker tracker, int touchX, int touchY, long eventTime) {
-        tracker.onDownEvent(touchX, touchY, eventTime);
+    private void onDownEvent(PointerTracker tracker, int x, int y, long eventTime) {
+        tracker.onDownEvent(x, y, eventTime);
         mPointerQueue.add(tracker);
     }
 
-    private void onUpEvent(PointerTracker tracker, int touchX, int touchY, long eventTime) {
+    private void onUpEvent(PointerTracker tracker, int x, int y, long eventTime) {
         int index = mPointerQueue.lastIndexOf(tracker);
         if (index >= 0) {
             mPointerQueue.releasePointersOlderThan(tracker, eventTime);
@@ -1175,12 +1165,12 @@
             Log.w(TAG, "onUpEvent: corresponding down event not found for pointer "
                     + tracker.mPointerId);
         }
-        tracker.onUpEvent(touchX, touchY, eventTime);
+        tracker.onUpEvent(x, y, eventTime);
         mPointerQueue.remove(tracker);
     }
 
-    private void onCancelEvent(PointerTracker tracker, int touchX, int touchY, long eventTime) {
-        tracker.onCancelEvent(touchX, touchY, eventTime);
+    private void onCancelEvent(PointerTracker tracker, int x, int y, long eventTime) {
+        tracker.onCancelEvent(x, y, eventTime);
         mPointerQueue.remove(tracker);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java
index f5f2c11..5b5cbe5 100644
--- a/java/src/com/android/inputmethod/latin/PointerTracker.java
+++ b/java/src/com/android/inputmethod/latin/PointerTracker.java
@@ -27,7 +27,7 @@
 public class PointerTracker {
     private static final String TAG = "PointerTracker";
     private static final boolean DEBUG = false;
-    private static final boolean DEBUG_MOVE = true && DEBUG;
+    private static final boolean DEBUG_MOVE = DEBUG && true;
 
     public interface UIProxy {
         public void invalidateKey(Key key);
@@ -139,12 +139,12 @@
         }
     }
 
-    public void onDownEvent(int touchX, int touchY, long eventTime) {
-        int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null);
+    public void onDownEvent(int x, int y, long eventTime) {
+        int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null);
         mCurrentKey = keyIndex;
-        mStartX = touchX;
-        mStartY = touchY;
-        startMoveDebouncing(touchX, touchY);
+        mStartX = x;
+        mStartY = y;
+        startMoveDebouncing(x, y);
         startTimeDebouncing(eventTime);
         checkMultiTap(eventTime, keyIndex);
         if (mListener != null) {
@@ -159,19 +159,19 @@
             mHandler.startLongPressTimer(LONGPRESS_TIMEOUT, keyIndex, this);
         }
         showKeyPreviewAndUpdateKey(keyIndex);
-        updateMoveDebouncing(touchX, touchY);
+        updateMoveDebouncing(x, y);
         if (DEBUG)
-            debugLog("onDownEvent:", touchX, touchY);
+            debugLog("onDownEvent:", x, y);
     }
 
-    public void onMoveEvent(int touchX, int touchY, long eventTime) {
-        int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null);
+    public void onMoveEvent(int x, int y, long eventTime) {
+        int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null);
         if (isValidKeyIndex(keyIndex)) {
             if (mCurrentKey == NOT_A_KEY) {
                 updateTimeDebouncing(eventTime);
                 mCurrentKey = keyIndex;
                 mHandler.startLongPressTimer(LONGPRESS_TIMEOUT, keyIndex, this);
-            } else if (isMinorMoveBounce(touchX, touchY, keyIndex, mCurrentKey)) {
+            } else if (isMinorMoveBounce(x, y, keyIndex, mCurrentKey)) {
                 updateTimeDebouncing(eventTime);
             } else {
                 resetMultiTap();
@@ -190,19 +190,19 @@
          * should not be showed as popup preview.
          */
         showKeyPreviewAndUpdateKey(isMinorTimeBounce() ? mLastKey : mCurrentKey);
-        updateMoveDebouncing(touchX, touchY);
+        updateMoveDebouncing(x, y);
         if (DEBUG_MOVE)
-            debugLog("onMoveEvent:", touchX, touchY);
+            debugLog("onMoveEvent:", x, y);
     }
 
-    public void onUpEvent(int touchX, int touchY, long eventTime) {
+    public void onUpEvent(int x, int y, long eventTime) {
         if (DEBUG)
-            debugLog("onUpEvent  :", touchX, touchY);
-        int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null);
+            debugLog("onUpEvent  :", x, y);
+        int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null);
         boolean wasInKeyRepeat = mHandler.isInKeyRepeat();
         mHandler.cancelKeyTimers();
         mHandler.cancelPopupPreview();
-        if (isMinorMoveBounce(touchX, touchY, keyIndex, mCurrentKey)) {
+        if (isMinorMoveBounce(x, y, keyIndex, mCurrentKey)) {
             updateTimeDebouncing(eventTime);
         } else {
             resetMultiTap();
@@ -211,21 +211,21 @@
         }
         if (isMinorTimeBounce()) {
             mCurrentKey = mLastKey;
-            touchX = mLastCodeX;
-            touchY = mLastCodeY;
+            x = mLastCodeX;
+            y = mLastCodeY;
         }
         showKeyPreviewAndUpdateKey(NOT_A_KEY);
         // If we're not on a repeating key (which sends on a DOWN event)
         if (!wasInKeyRepeat && !mProxy.isMiniKeyboardOnScreen()) {
-            detectAndSendKey(mCurrentKey, touchX, touchY, eventTime);
+            detectAndSendKey(mCurrentKey, (int)x, (int)y, eventTime);
         }
         if (isValidKeyIndex(keyIndex))
             mProxy.invalidateKey(mKeys[keyIndex]);
     }
 
-    public void onCancelEvent(int touchX, int touchY, long eventTime) {
+    public void onCancelEvent(int x, int y, long eventTime) {
         if (DEBUG)
-            debugLog("onCancelEvt:", touchX, touchY);
+            debugLog("onCancelEvt:", x, y);
         mHandler.cancelKeyTimers();
         mHandler.cancelPopupPreview();
         mProxy.dismissPopupKeyboard();
@@ -244,6 +244,14 @@
         }
     }
 
+    public int getLastX() {
+        return mLastX;
+    }
+
+    public int getLastY() {
+        return mLastY;
+    }
+
     // These package scope methods are only for debugging purpose.
     /* package */ int getStartX() {
         return mStartX;
@@ -253,14 +261,6 @@
         return mStartY;
     }
 
-    /* package */ int getLastX() {
-        return mLastX;
-    }
-
-    /* package */ int getLastY() {
-        return mLastY;
-    }
-
     private void startMoveDebouncing(int x, int y) {
         mLastCodeX = x;
         mLastCodeY = y;
@@ -425,8 +425,7 @@
             int primaryCode = key.codes[0];
             code = String.format((primaryCode < 0) ? "%4d" : "0x%02x", primaryCode);
         }
-         Log.d(TAG,
-                String.format("%s [%d] %d,%d %s %s", title, mPointerId, x, y, code,
-                        isModifier() ? "modifier" : ""));
+        Log.d(TAG, String.format("%s [%d] %3d,%3d %s %s", title, mPointerId, x, y, code,
+                isModifier() ? "modifier" : ""));
     }
 }
\ No newline at end of file
diff --git a/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java b/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java
index 6ee0055..d17bedb 100644
--- a/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java
+++ b/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java
@@ -27,35 +27,32 @@
     private int[] mDistances = new int[MAX_NEARBY_KEYS];
 
     @Override
-    public int[] newCodeArray() {
-        int[] codes = new int[MAX_NEARBY_KEYS];
-        Arrays.fill(codes, LatinKeyboardBaseView.NOT_A_KEY);
-        return codes;
+    protected int getMaxNearbyKeys() {
+        return MAX_NEARBY_KEYS;
     }
 
     @Override
     public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys) {
-        final Key[] keys = mKeys;
-        if (keys == null)
-            throw new IllegalStateException("keyboard isn't set");
-        // mKeyboard is guaranteed not null at setKeybaord() method
+        final Key[] keys = getKeys();
+        final int touchX = getTouchX(x);
+        final int touchY = getTouchY(y);
         int primaryIndex = LatinKeyboardBaseView.NOT_A_KEY;
         int closestKey = LatinKeyboardBaseView.NOT_A_KEY;
         int closestKeyDist = mProximityThresholdSquare + 1;
         int[] distances = mDistances;
         Arrays.fill(distances, Integer.MAX_VALUE);
-        int [] nearestKeyIndices = mKeyboard.getNearestKeys(x, y);
+        int [] nearestKeyIndices = mKeyboard.getNearestKeys(touchX, touchY);
         final int keyCount = nearestKeyIndices.length;
         for (int i = 0; i < keyCount; i++) {
             final Key key = keys[nearestKeyIndices[i]];
             int dist = 0;
-            boolean isInside = key.isInside(x,y);
+            boolean isInside = key.isInside(touchX, touchY);
             if (isInside) {
                 primaryIndex = nearestKeyIndices[i];
             }
 
             if (((mProximityCorrectOn
-                    && (dist = key.squaredDistanceFrom(x, y)) < mProximityThresholdSquare)
+                    && (dist = key.squaredDistanceFrom(touchX, touchY)) < mProximityThresholdSquare)
                     || isInside)
                     && key.codes[0] > 32) {
                 // Find insertion point