Move motion event dispatcher to PointerTracker

Change-Id: I967bf4629b7d1002be6aff6007dc03d2db05c562
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 5334b45..e00e4b5 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -1055,26 +1055,10 @@
             ResearchLogger.mainKeyboardView_processMotionEvent(me);
         }
 
-        final int action = me.getActionMasked();
-        final long eventTime = me.getEventTime();
-        if (action == MotionEvent.ACTION_MOVE) {
-            final int pointerCount = me.getPointerCount();
-            for (int index = 0; index < pointerCount; index++) {
-                final int id = me.getPointerId(index);
-                final PointerTracker tracker = PointerTracker.getPointerTracker(id, this);
-                final int x = (int)me.getX(index);
-                final int y = (int)me.getY(index);
-                tracker.onMoveEvent(x, y, eventTime, me);
-            }
-        } else {
-            final int index = me.getActionIndex();
-            final int id = me.getPointerId(index);
-            final int x = (int)me.getX(index);
-            final int y = (int)me.getY(index);
-            final PointerTracker tracker = PointerTracker.getPointerTracker(id, this);
-            tracker.processMotionEvent(action, x, y, eventTime, this);
-        }
-
+        final int index = me.getActionIndex();
+        final int id = me.getPointerId(index);
+        final PointerTracker tracker = PointerTracker.getPointerTracker(id, this);
+        tracker.processMotionEvent(me, this);
         return true;
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index bbaf969..ab5fee9 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -870,8 +870,23 @@
         mListener.onCancelBatchInput();
     }
 
-    public void processMotionEvent(final int action, final int x, final int y, final long eventTime,
-            final KeyEventHandler handler) {
+    public void processMotionEvent(final MotionEvent me, final KeyEventHandler handler) {
+        final int action = me.getActionMasked();
+        final long eventTime = me.getEventTime();
+        if (action == MotionEvent.ACTION_MOVE) {
+            final int pointerCount = me.getPointerCount();
+            for (int index = 0; index < pointerCount; index++) {
+                final int id = me.getPointerId(index);
+                final PointerTracker tracker = getPointerTracker(id, handler);
+                final int x = (int)me.getX(index);
+                final int y = (int)me.getY(index);
+                tracker.onMoveEvent(x, y, eventTime, me);
+            }
+            return;
+        }
+        final int index = me.getActionIndex();
+        final int x = (int)me.getX(index);
+        final int y = (int)me.getY(index);
         switch (action) {
         case MotionEvent.ACTION_DOWN:
         case MotionEvent.ACTION_POINTER_DOWN:
@@ -881,16 +896,13 @@
         case MotionEvent.ACTION_POINTER_UP:
             onUpEvent(x, y, eventTime);
             break;
-        case MotionEvent.ACTION_MOVE:
-            onMoveEvent(x, y, eventTime, null);
-            break;
         case MotionEvent.ACTION_CANCEL:
             onCancelEvent(x, y, eventTime);
             break;
         }
     }
 
-    public void onDownEvent(final int x, final int y, final long eventTime,
+    private void onDownEvent(final int x, final int y, final long eventTime,
             final KeyEventHandler handler) {
         if (DEBUG_EVENT) {
             printTouchEvent("onDownEvent:", x, y, eventTime);
@@ -1005,7 +1017,7 @@
         }
     }
 
-    public void onMoveEvent(final int x, final int y, final long eventTime, final MotionEvent me) {
+    private void onMoveEvent(final int x, final int y, final long eventTime, final MotionEvent me) {
         if (DEBUG_MOVE_EVENT) {
             printTouchEvent("onMoveEvent:", x, y, eventTime);
         }
@@ -1193,7 +1205,7 @@
         }
     }
 
-    public void onUpEvent(final int x, final int y, final long eventTime) {
+    private void onUpEvent(final int x, final int y, final long eventTime) {
         if (DEBUG_EVENT) {
             printTouchEvent("onUpEvent  :", x, y, eventTime);
         }
@@ -1293,7 +1305,7 @@
         sPointerTrackerQueue.remove(this);
     }
 
-    public void onCancelEvent(final int x, final int y, final long eventTime) {
+    private void onCancelEvent(final int x, final int y, final long eventTime) {
         if (DEBUG_EVENT) {
             printTouchEvent("onCancelEvt:", x, y, eventTime);
         }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/NonDistinctMultitouchHelper.java b/java/src/com/android/inputmethod/keyboard/internal/NonDistinctMultitouchHelper.java
index 53fff69..a0935b9 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/NonDistinctMultitouchHelper.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/NonDistinctMultitouchHelper.java
@@ -29,56 +29,67 @@
 
     private int mOldPointerCount = 1;
     private Key mOldKey;
+    private int[] mLastCoords = CoordinateUtils.newInstance();
 
     public void processMotionEvent(final MotionEvent me, final KeyEventHandler keyEventHandler) {
         final int pointerCount = me.getPointerCount();
         final int oldPointerCount = mOldPointerCount;
         mOldPointerCount = pointerCount;
-        // Ignore continuous multitouch events because we can't trust the coordinates in mulitouch
-        // events.
+        // Ignore continuous multi-touch events because we can't trust the coordinates
+        // in multi-touch events.
         if (pointerCount > 1 && oldPointerCount > 1) {
             return;
         }
 
+        // Use only main (id=0) pointer tracker.
+        final PointerTracker mainTracker = PointerTracker.getPointerTracker(0, keyEventHandler);
         final int action = me.getActionMasked();
         final int index = me.getActionIndex();
         final long eventTime = me.getEventTime();
-        final int x = (int)me.getX(index);
-        final int y = (int)me.getY(index);
-        // Use only main (id=0) pointer tracker.
-        final PointerTracker mainTracker = PointerTracker.getPointerTracker(0, keyEventHandler);
+        final long downTime = me.getDownTime();
 
-        // In single touch.
+        // In single-touch.
         if (oldPointerCount == 1 && pointerCount == 1) {
-            mainTracker.processMotionEvent(action, x, y, eventTime, keyEventHandler);
+            if (me.getPointerId(index) == mainTracker.mPointerId) {
+                mainTracker.processMotionEvent(me, keyEventHandler);
+                return;
+            }
+            // Inject a copied event.
+            injectMotionEvent(action, me.getX(index), me.getY(index), downTime, eventTime,
+                    mainTracker, keyEventHandler);
             return;
         }
 
         // Single-touch to multi-touch transition.
         if (oldPointerCount == 1 && pointerCount == 2) {
-            // Send an up event for the last pointer, be cause we can't trust the corrdinates of
-            // this multitouch event.
-            final int[] lastCoords = CoordinateUtils.newInstance();
-            mainTracker.getLastCoordinates(lastCoords);
-            mOldKey = mainTracker.getKeyOn(
-                    CoordinateUtils.x(lastCoords), CoordinateUtils.y(lastCoords));
-            // TODO: Stop calling PointerTracker.onUpEvent directly.
-            mainTracker.onUpEvent(
-                    CoordinateUtils.x(lastCoords), CoordinateUtils.y(lastCoords), eventTime);
+            // Send an up event for the last pointer, be cause we can't trust the coordinates of
+            // this multi-touch event.
+            mainTracker.getLastCoordinates(mLastCoords);
+            final int x = CoordinateUtils.x(mLastCoords);
+            final int y = CoordinateUtils.y(mLastCoords);
+            mOldKey = mainTracker.getKeyOn(x, y);
+            // Inject an artifact up event for the old key.
+            injectMotionEvent(MotionEvent.ACTION_UP, x, y, downTime, eventTime,
+                    mainTracker, keyEventHandler);
             return;
         }
 
-        // Multi-touch to single touch transition.
+        // Multi-touch to single-touch transition.
         if (oldPointerCount == 2 && pointerCount == 1) {
-            // Send a down event for the latest pointer if the key is different from the
-            // previous key.
+            // Send a down event for the latest pointer if the key is different from the previous
+            // key.
+            final int x = (int)me.getX(index);
+            final int y = (int)me.getY(index);
             final Key newKey = mainTracker.getKeyOn(x, y);
             if (mOldKey != newKey) {
-                // TODO: Stop calling PointerTracker.onDownEvent directly.
-                mainTracker.onDownEvent(x, y, eventTime, keyEventHandler);
+                // Inject an artifact down event for the new key.
+                // An artifact up event for the new key will usually be injected as a single-touch.
+                injectMotionEvent(MotionEvent.ACTION_DOWN, x, y, downTime, eventTime,
+                        mainTracker, keyEventHandler);
                 if (action == MotionEvent.ACTION_UP) {
-                    // TODO: Stop calling PointerTracker.onUpEvent directly.
-                    mainTracker.onUpEvent(x, y, eventTime);
+                    // Inject an artifact up event for the new key also.
+                    injectMotionEvent(MotionEvent.ACTION_UP, x, y, downTime, eventTime,
+                            mainTracker, keyEventHandler);
                 }
             }
             return;
@@ -87,4 +98,16 @@
         Log.w(TAG, "Unknown touch panel behavior: pointer count is "
                 + pointerCount + " (previously " + oldPointerCount + ")");
     }
+
+    private static void injectMotionEvent(final int action, final float x, final float y,
+            final long downTime, final long eventTime, final PointerTracker tracker,
+            final KeyEventHandler handler) {
+        final MotionEvent me = MotionEvent.obtain(
+                downTime, eventTime, action, x, y, 0 /* metaState */);
+        try {
+            tracker.processMotionEvent(me, handler);
+        } finally {
+            me.recycle();
+        }
+    }
 }