Merge "Fix : Bouncing Extract Text when correcting multiple lines of text." into gingerbread
diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java
index a78e2b8..3ae2e1c 100644
--- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java
+++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java
@@ -345,7 +345,7 @@
             return -1;
         }
 
-        public void releasePointersOlderThan(PointerTracker tracker, long eventTime) {
+        public void releaseAllPointersOlderThan(PointerTracker tracker, long eventTime) {
             LinkedList<PointerTracker> queue = mQueue;
             int oldestPos = 0;
             for (PointerTracker t = queue.get(oldestPos); t != tracker; t = queue.get(oldestPos)) {
@@ -353,11 +353,24 @@
                     oldestPos++;
                 } else {
                     t.onUpEvent(t.getLastX(), t.getLastY(), eventTime);
+                    t.setAlreadyProcessed();
                     queue.remove(oldestPos);
                 }
             }
         }
 
+        public void releaseAllPointersExcept(PointerTracker tracker, long eventTime) {
+            for (PointerTracker t : mQueue) {
+                if (t == tracker)
+                    continue;
+                t.onUpEvent(t.getLastX(), t.getLastY(), eventTime);
+                t.setAlreadyProcessed();
+            }
+            mQueue.clear();
+            if (tracker != null)
+                mQueue.add(tracker);
+        }
+
         public void remove(PointerTracker tracker) {
             mQueue.remove(tracker);
         }
@@ -1246,17 +1259,28 @@
     }
 
     private void onDownEvent(PointerTracker tracker, int x, int y, long eventTime) {
+        if (tracker.isOnModifierKey(x, y)) {
+            // Before processing a down event of modifier key, all pointers already being tracked
+            // should be released.
+            mPointerQueue.releaseAllPointersExcept(null, eventTime);
+        }
         tracker.onDownEvent(x, y, eventTime);
         mPointerQueue.add(tracker);
     }
 
     private void onUpEvent(PointerTracker tracker, int x, int y, long eventTime) {
-        int index = mPointerQueue.lastIndexOf(tracker);
-        if (index >= 0) {
-            mPointerQueue.releasePointersOlderThan(tracker, eventTime);
+        if (tracker.isModifier()) {
+            // Before processing an up event of modifier key, all pointers already being tracked
+            // should be released.
+            mPointerQueue.releaseAllPointersExcept(tracker, eventTime);
         } else {
-            Log.w(TAG, "onUpEvent: corresponding down event not found for pointer "
-                    + tracker.mPointerId);
+            int index = mPointerQueue.lastIndexOf(tracker);
+            if (index >= 0) {
+                mPointerQueue.releaseAllPointersOlderThan(tracker, eventTime);
+            } else {
+                Log.w(TAG, "onUpEvent: corresponding down event not found for pointer "
+                        + tracker.mPointerId);
+            }
         }
         tracker.onUpEvent(x, y, eventTime);
         mPointerQueue.remove(tracker);
diff --git a/java/src/com/android/inputmethod/latin/MiniKeyboardKeyDetector.java b/java/src/com/android/inputmethod/latin/MiniKeyboardKeyDetector.java
index 709d082..356e62d 100644
--- a/java/src/com/android/inputmethod/latin/MiniKeyboardKeyDetector.java
+++ b/java/src/com/android/inputmethod/latin/MiniKeyboardKeyDetector.java
@@ -41,19 +41,19 @@
         final Key[] keys = getKeys();
         final int touchX = getTouchX(x);
         final int touchY = getTouchY(y);
-        int closestKey = LatinKeyboardBaseView.NOT_A_KEY;
+        int closestKeyIndex = LatinKeyboardBaseView.NOT_A_KEY;
         int closestKeyDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
         final int keyCount = keys.length;
         for (int i = 0; i < keyCount; i++) {
             final Key key = keys[i];
             int dist = key.squaredDistanceFrom(touchX, touchY);
             if (dist < closestKeyDist) {
-                closestKey = i;
+                closestKeyIndex = i;
                 closestKeyDist = dist;
             }
         }
-        if (allKeys != null && closestKey != LatinKeyboardBaseView.NOT_A_KEY)
-            allKeys[0] = closestKey;
-        return closestKey;
+        if (allKeys != null && closestKeyIndex != LatinKeyboardBaseView.NOT_A_KEY)
+            allKeys[0] = keys[closestKeyIndex].codes[0];
+        return closestKeyIndex;
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java
index 958e576..a612c8e 100644
--- a/java/src/com/android/inputmethod/latin/PointerTracker.java
+++ b/java/src/com/android/inputmethod/latin/PointerTracker.java
@@ -123,8 +123,8 @@
         return isValidKeyIndex(keyIndex) ? mKeys[keyIndex] : null;
     }
 
-    public boolean isModifier() {
-        Key key = getKey(mCurrentKey);
+    private boolean isModifierInternal(int keyIndex) {
+        Key key = getKey(keyIndex);
         if (key == null)
             return false;
         int primaryCode = key.codes[0];
@@ -132,6 +132,14 @@
                 || primaryCode == Keyboard.KEYCODE_MODE_CHANGE;
     }
 
+    public boolean isModifier() {
+        return isModifierInternal(mCurrentKey);
+    }
+
+    public boolean isOnModifierKey(int x, int y) {
+        return isModifierInternal(mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null));
+    }
+
     public void updateKey(int keyIndex) {
         if (mKeyAlreadyProcessed)
             return;