diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 7c6e4dc4e..dd552f0fc 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -1359,13 +1359,13 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { if (pointerCount == 1 && oldPointerCount == 2) { // Multi-touch to single touch transition. // Send a down event for the latest pointer. - tracker.onDownEvent(x, y, eventTime); + tracker.onDownEvent(x, y, eventTime, null); } else if (pointerCount == 2 && oldPointerCount == 1) { // Single-touch to multi-touch transition. // Send an up event for the last pointer. - tracker.onUpEvent(tracker.getLastX(), tracker.getLastY(), eventTime); + tracker.onUpEvent(tracker.getLastX(), tracker.getLastY(), eventTime, null); } else if (pointerCount == 1 && oldPointerCount == 1) { - tracker.onTouchEvent(action, x, y, eventTime); + tracker.onTouchEvent(action, x, y, eventTime, null); } else { Log.w(TAG, "Unknown touch panel behavior: pointer count is " + pointerCount + " (old " + oldPointerCount + ")"); @@ -1373,24 +1373,25 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { return true; } + final PointerTrackerQueue queue = mPointerQueue; if (action == MotionEvent.ACTION_MOVE) { for (int i = 0; i < pointerCount; i++) { - PointerTracker tracker = getPointerTracker(me.getPointerId(i)); - tracker.onMoveEvent((int)me.getX(i), (int)me.getY(i), eventTime); + final PointerTracker tracker = getPointerTracker(me.getPointerId(i)); + tracker.onMoveEvent((int)me.getX(i), (int)me.getY(i), eventTime, queue); } } else { - PointerTracker tracker = getPointerTracker(id); + final PointerTracker tracker = getPointerTracker(id); switch (action) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_POINTER_DOWN: - onDownEvent(tracker, x, y, eventTime); + tracker.onDownEvent(x, y, eventTime, queue); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: - onUpEvent(tracker, x, y, eventTime); + tracker.onUpEvent(x, y, eventTime, queue); break; case MotionEvent.ACTION_CANCEL: - onCancelEvent(tracker, x, y, eventTime); + tracker.onCancelEvent(x, y, eventTime, queue); break; } } @@ -1398,39 +1399,6 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { return true; } - 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) { - if (tracker.isModifier()) { - // Before processing an up event of modifier key, all pointers already being tracked - // should be released. - mPointerQueue.releaseAllPointersExcept(tracker, eventTime); - } else { - 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); - } - - private void onCancelEvent(PointerTracker tracker, int x, int y, long eventTime) { - tracker.onCancelEvent(x, y, eventTime); - mPointerQueue.remove(tracker); - } - protected void onSwipeDown() { mKeyboardActionListener.onSwipeDown(); } diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 9bfe9113d..552ab528b 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -27,6 +27,7 @@ import java.util.Arrays; public class PointerTracker { private static final String TAG = PointerTracker.class.getSimpleName(); + private static final boolean ENABLE_ASSERTION = false; private static final boolean DEBUG_EVENT = false; private static final boolean DEBUG_MOVE_EVENT = false; private static final boolean DEBUG_LISTENER = false; @@ -46,7 +47,6 @@ public class PointerTracker { // Miscellaneous constants private static final int NOT_A_KEY = KeyDetector.NOT_A_KEY; - private static final int[] KEY_DELETE = { Keyboard.CODE_DELETE }; private final UIProxy mProxy; private final UIHandler mHandler; @@ -181,7 +181,7 @@ public class PointerTracker { return isModifierInternal(mKeyState.getKeyIndex()); } - public boolean isOnModifierKey(int x, int y) { + private boolean isOnModifierKey(int x, int y) { return isModifierInternal(mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null)); } @@ -220,28 +220,51 @@ public class PointerTracker { mKeyAlreadyProcessed = true; } - public void onTouchEvent(int action, int x, int y, long eventTime) { + private void checkAssertion(PointerTrackerQueue queue) { + if (mHasDistinctMultitouch && queue == null) + throw new RuntimeException( + "PointerTrackerQueue must be passed on distinct multi touch device"); + if (!mHasDistinctMultitouch && queue != null) + throw new RuntimeException( + "PointerTrackerQueue must be null on non-distinct multi touch device"); + } + + public void onTouchEvent(int action, int x, int y, long eventTime, PointerTrackerQueue queue) { switch (action) { case MotionEvent.ACTION_MOVE: - onMoveEvent(x, y, eventTime); + onMoveEvent(x, y, eventTime, queue); break; case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_POINTER_DOWN: - onDownEvent(x, y, eventTime); + onDownEvent(x, y, eventTime, queue); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: - onUpEvent(x, y, eventTime); + onUpEvent(x, y, eventTime, queue); break; case MotionEvent.ACTION_CANCEL: - onCancelEvent(x, y, eventTime); + onCancelEvent(x, y, eventTime, queue); break; } } - public void onDownEvent(int x, int y, long eventTime) { + public void onDownEvent(int x, int y, long eventTime, PointerTrackerQueue queue) { + if (ENABLE_ASSERTION) checkAssertion(queue); if (DEBUG_EVENT) printTouchEvent("onDownEvent:", x, y, eventTime); + + if (queue != null) { + if (isOnModifierKey(x, y)) { + // Before processing a down event of modifier key, all pointers already being + // tracked should be released. + queue.releaseAllPointers(eventTime); + } + queue.add(this); + } + onDownEventInternal(x, y, eventTime); + } + + public void onDownEventInternal(int x, int y, long eventTime) { int keyIndex = mKeyState.onDownKey(x, y, eventTime); // Sliding key is allowed when 1) enabled by configuration, 2) this pointer starts sliding // from modifier key, or 3) this pointer is on mini-keyboard. @@ -267,7 +290,8 @@ public class PointerTracker { showKeyPreviewAndUpdateKeyGraphics(keyIndex); } - public void onMoveEvent(int x, int y, long eventTime) { + public void onMoveEvent(int x, int y, long eventTime, PointerTrackerQueue queue) { + if (ENABLE_ASSERTION) checkAssertion(queue); if (DEBUG_MOVE_EVENT) printTouchEvent("onMoveEvent:", x, y, eventTime); if (mKeyAlreadyProcessed) @@ -318,11 +342,31 @@ public class PointerTracker { showKeyPreviewAndUpdateKeyGraphics(mKeyState.getKeyIndex()); } - public void onUpEvent(int pointX, int pointY, long eventTime) { - int x = pointX; - int y = pointY; + public void onUpEvent(int x, int y, long eventTime, PointerTrackerQueue queue) { + if (ENABLE_ASSERTION) checkAssertion(queue); if (DEBUG_EVENT) printTouchEvent("onUpEvent :", x, y, eventTime); + + if (queue != null) { + if (isModifier()) { + // Before processing an up event of modifier key, all pointers already being + // tracked should be released. + queue.releaseAllPointersExcept(this, eventTime); + } else { + queue.releaseAllPointersOlderThan(this, eventTime); + } + queue.remove(this); + } + onUpEventInternal(x, y, eventTime); + } + + public void onUpEventForRelease(int x, int y, long eventTime) { + onUpEventInternal(x, y, eventTime); + } + + private void onUpEventInternal(int pointX, int pointY, long eventTime) { + int x = pointX; + int y = pointY; mHandler.cancelKeyTimers(); mHandler.cancelPopupPreview(); showKeyPreviewAndUpdateKeyGraphics(NOT_A_KEY); @@ -345,9 +389,17 @@ public class PointerTracker { mProxy.invalidateKey(mKeys[keyIndex]); } - public void onCancelEvent(int x, int y, long eventTime) { + public void onCancelEvent(int x, int y, long eventTime, PointerTrackerQueue queue) { + if (ENABLE_ASSERTION) checkAssertion(queue); if (DEBUG_EVENT) printTouchEvent("onCancelEvt:", x, y, eventTime); + + if (queue != null) + queue.remove(this); + onCancelEventInternal(x, y, eventTime); + } + + private void onCancelEventInternal(int x, int y, long eventTime) { mHandler.cancelKeyTimers(); mHandler.cancelPopupPreview(); showKeyPreviewAndUpdateKeyGraphics(NOT_A_KEY); diff --git a/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java b/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java index 236c9d550..928f3cdc1 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java @@ -25,35 +25,32 @@ public class PointerTrackerQueue { mQueue.add(tracker); } - public int lastIndexOf(PointerTracker tracker) { - LinkedList queue = mQueue; - for (int index = queue.size() - 1; index >= 0; index--) { - PointerTracker t = queue.get(index); - if (t == tracker) - return index; - } - return -1; - } - public void releaseAllPointersOlderThan(PointerTracker tracker, long eventTime) { + if (mQueue.lastIndexOf(tracker) < 0) { + return; + } LinkedList queue = mQueue; int oldestPos = 0; for (PointerTracker t = queue.get(oldestPos); t != tracker; t = queue.get(oldestPos)) { if (t.isModifier()) { oldestPos++; } else { - t.onUpEvent(t.getLastX(), t.getLastY(), eventTime); + t.onUpEventForRelease(t.getLastX(), t.getLastY(), eventTime); t.setAlreadyProcessed(); queue.remove(oldestPos); } } } + public void releaseAllPointers(long eventTime) { + releaseAllPointersExcept(null, eventTime); + } + public void releaseAllPointersExcept(PointerTracker tracker, long eventTime) { for (PointerTracker t : mQueue) { if (t == tracker) continue; - t.onUpEvent(t.getLastX(), t.getLastY(), eventTime); + t.onUpEventForRelease(t.getLastX(), t.getLastY(), eventTime); t.setAlreadyProcessed(); } mQueue.clear();