diff options
Diffstat (limited to 'java/src/com/android/inputmethod/keyboard/PointerTracker.java')
-rw-r--r-- | java/src/com/android/inputmethod/keyboard/PointerTracker.java | 478 |
1 files changed, 255 insertions, 223 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index d0f7cb276..296a45faf 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -27,6 +27,7 @@ import com.android.inputmethod.keyboard.internal.GestureStroke.GestureStrokePara import com.android.inputmethod.keyboard.internal.GestureStrokeWithPreviewPoints; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.latin.CollectionUtils; +import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.InputPointers; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; @@ -93,6 +94,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element { public void cancelDoubleTapTimer(); public boolean isInDoubleTapTimeout(); public void cancelKeyTimers(); + public void startUpdateBatchInputTimer(PointerTracker tracker); + public void cancelAllUpdateBatchInputTimers(); public static class Adapter implements TimerProxy { @Override @@ -115,6 +118,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element { public boolean isInDoubleTapTimeout() { return false; } @Override public void cancelKeyTimers() {} + @Override + public void startUpdateBatchInputTimer(PointerTracker tracker) {} + @Override + public void cancelAllUpdateBatchInputTimers() {} } } @@ -156,7 +163,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { private static final boolean sNeedsProximateBogusDownMoveUpEventHack = true; private static final ArrayList<PointerTracker> sTrackers = CollectionUtils.newArrayList(); - private static PointerTrackerQueue sPointerTrackerQueue; + private static final PointerTrackerQueue sPointerTrackerQueue = new PointerTrackerQueue(); public final int mPointerId; @@ -304,8 +311,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element { // true if keyboard layout has been changed. private boolean mKeyboardLayoutHasBeenChanged; - // true if event is already translated to a key action. - private boolean mKeyAlreadyProcessed; + // true if this pointer is no longer tracking touch event. + private boolean mIsTrackingCanceled; // true if this pointer has been long-pressed and is showing a more keys panel. private boolean mIsShowingMoreKeysPanel; @@ -325,13 +332,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { private final GestureStrokeWithPreviewPoints mGestureStrokeWithPreviewPoints; - public static void init(boolean hasDistinctMultitouch, - boolean needsPhantomSuddenMoveEventHack) { - if (hasDistinctMultitouch) { - sPointerTrackerQueue = new PointerTrackerQueue(); - } else { - sPointerTrackerQueue = null; - } + public static void init(final boolean needsPhantomSuddenMoveEventHack) { sNeedsPhantomSuddenMoveEventHack = needsPhantomSuddenMoveEventHack; sParams = PointerTrackerParams.DEFAULT; sGestureStrokeParams = GestureStrokeParams.DEFAULT; @@ -375,7 +376,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } public static boolean isAnyInSlidingKeyInput() { - return sPointerTrackerQueue != null ? sPointerTrackerQueue.isAnyInSlidingKeyInput() : false; + return sPointerTrackerQueue.isAnyInSlidingKeyInput(); } public static void setKeyboardActionListener(final KeyboardActionListener listener) { @@ -453,8 +454,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element { final boolean altersCode = key.altCodeWhileTyping() && mTimerProxy.isTypingState(); final int code = altersCode ? key.getAltCode() : primaryCode; if (DEBUG_LISTENER) { - final String output = code == Keyboard.CODE_OUTPUT_TEXT - ? key.getOutputText() : Keyboard.printableCode(code); + final String output = code == Constants.CODE_OUTPUT_TEXT + ? key.getOutputText() : Constants.printableCode(code); Log.d(TAG, String.format("[%d] onCodeInput: %4d %4d %s%s%s", mPointerId, x, y, output, ignoreModifierKey ? " ignoreModifier" : "", altersCode ? " altersCode" : "", key.isEnabled() ? "" : " disabled")); @@ -469,9 +470,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element { // Even if the key is disabled, it should respond if it is in the altCodeWhileTyping state. if (key.isEnabled() || altersCode) { sTimeRecorder.onCodeInput(code, eventTime); - if (code == Keyboard.CODE_OUTPUT_TEXT) { + if (code == Constants.CODE_OUTPUT_TEXT) { mListener.onTextInput(key.getOutputText()); - } else if (code != Keyboard.CODE_UNSPECIFIED) { + } else if (code != Constants.CODE_UNSPECIFIED) { mListener.onCodeInput(code, x, y); } } @@ -487,7 +488,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { final boolean ignoreModifierKey = mIsInSlidingKeyInputFromModifier && key.isModifier(); if (DEBUG_LISTENER) { Log.d(TAG, String.format("[%d] onRelease : %s%s%s%s", mPointerId, - Keyboard.printableCode(primaryCode), + Constants.printableCode(primaryCode), withSliding ? " sliding" : "", ignoreModifierKey ? " ignoreModifier" : "", key.isEnabled() ? "": " disabled")); } @@ -522,7 +523,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { mKeyboard = keyDetector.getKeyboard(); final int keyWidth = mKeyboard.mMostCommonKeyWidth; final int keyHeight = mKeyboard.mMostCommonKeyHeight; - mGestureStrokeWithPreviewPoints.setKeyboardGeometry(keyWidth); + mGestureStrokeWithPreviewPoints.setKeyboardGeometry(keyWidth, mKeyboard.mOccupiedHeight); final Key newKey = mKeyDetector.detectHitKey(mKeyX, mKeyY); if (newKey != mCurrentKey) { if (mDrawingProxy != null) { @@ -682,7 +683,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } private static int getActivePointerTrackerCount() { - return (sPointerTrackerQueue == null) ? 1 : sPointerTrackerQueue.size(); + return sPointerTrackerQueue.size(); + } + + private static boolean isOldestTrackerInQueue(final PointerTracker tracker) { + return sPointerTrackerQueue.getOldestElement() == tracker; } private void mayStartBatchInput(final Key key) { @@ -702,47 +707,59 @@ public final class PointerTracker implements PointerTrackerQueue.Element { sLastRecognitionTime = 0; mListener.onStartBatchInput(); } - final boolean isOldestTracker = sPointerTrackerQueue.getOldestElement() == this; - mDrawingProxy.showGesturePreviewTrail(this, isOldestTracker); + mTimerProxy.cancelLongPressTimer(); + mDrawingProxy.showGesturePreviewTrail(this, isOldestTrackerInQueue(this)); + } + + public void updateBatchInputByTimer(final long eventTime) { + final int gestureTime = (int)(eventTime - sGestureFirstDownTime); + mGestureStrokeWithPreviewPoints.duplicateLastPointWith(gestureTime); + updateBatchInput(eventTime); } private void mayUpdateBatchInput(final long eventTime, final Key key) { if (key != null) { - synchronized (sAggregratedPointers) { - final GestureStroke stroke = mGestureStrokeWithPreviewPoints; - stroke.appendIncrementalBatchPoints(sAggregratedPointers); - final int size = sAggregratedPointers.getPointerSize(); - if (size > sLastRecognitionPointSize - && stroke.hasRecognitionTimePast(eventTime, sLastRecognitionTime)) { - sLastRecognitionPointSize = size; - sLastRecognitionTime = eventTime; - if (DEBUG_LISTENER) { - Log.d(TAG, String.format("[%d] onUpdateBatchInput: batchPoints=%d", - mPointerId, size)); - } - mListener.onUpdateBatchInput(sAggregratedPointers); + updateBatchInput(eventTime); + } + mDrawingProxy.showGesturePreviewTrail(this, isOldestTrackerInQueue(this)); + } + + private void updateBatchInput(final long eventTime) { + synchronized (sAggregratedPointers) { + final GestureStroke stroke = mGestureStrokeWithPreviewPoints; + stroke.appendIncrementalBatchPoints(sAggregratedPointers); + final int size = sAggregratedPointers.getPointerSize(); + if (size > sLastRecognitionPointSize + && stroke.hasRecognitionTimePast(eventTime, sLastRecognitionTime)) { + sLastRecognitionPointSize = size; + sLastRecognitionTime = eventTime; + if (DEBUG_LISTENER) { + Log.d(TAG, String.format("[%d] onUpdateBatchInput: batchPoints=%d", mPointerId, + size)); } + mTimerProxy.startUpdateBatchInputTimer(this); + mListener.onUpdateBatchInput(sAggregratedPointers); } } - final boolean isOldestTracker = sPointerTrackerQueue.getOldestElement() == this; - mDrawingProxy.showGesturePreviewTrail(this, isOldestTracker); } private void mayEndBatchInput(final long eventTime) { synchronized (sAggregratedPointers) { mGestureStrokeWithPreviewPoints.appendAllBatchPoints(sAggregratedPointers); if (getActivePointerTrackerCount() == 1) { - if (DEBUG_LISTENER) { - Log.d(TAG, String.format("[%d] onEndBatchInput : batchPoints=%d", - mPointerId, sAggregratedPointers.getPointerSize())); - } sInGesture = false; sTimeRecorder.onEndBatchInput(eventTime); - mListener.onEndBatchInput(sAggregratedPointers); + if (!mIsTrackingCanceled) { + if (DEBUG_LISTENER) { + Log.d(TAG, String.format("[%d] onEndBatchInput : batchPoints=%d", + mPointerId, sAggregratedPointers.getPointerSize())); + } + mTimerProxy.cancelAllUpdateBatchInputTimers(); + mListener.onEndBatchInput(sAggregratedPointers); + } } } - final boolean isOldestTracker = sPointerTrackerQueue.getOldestElement() == this; - mDrawingProxy.showGesturePreviewTrail(this, isOldestTracker); + mDrawingProxy.showGesturePreviewTrail(this, isOldestTrackerInQueue(this)); } public void processMotionEvent(final int action, final int x, final int y, final long eventTime, @@ -787,29 +804,26 @@ public final class PointerTracker implements PointerTrackerQueue.Element { if (ProductionFlag.IS_EXPERIMENTAL) { ResearchLogger.pointerTracker_onDownEvent(deltaT, distance * distance); } - mKeyAlreadyProcessed = true; + cancelTracking(); return; } } final Key key = getKeyOn(x, y); mBogusMoveEventDetector.onActualDownEvent(x, y); - final PointerTrackerQueue queue = sPointerTrackerQueue; - if (queue != null) { - if (key != null && key.isModifier()) { - // Before processing a down event of modifier key, all pointers already being - // tracked should be released. - queue.releaseAllPointers(eventTime); - } - queue.add(this); + if (key != null && key.isModifier()) { + // Before processing a down event of modifier key, all pointers already being + // tracked should be released. + sPointerTrackerQueue.releaseAllPointers(eventTime); } + sPointerTrackerQueue.add(this); onDownEventInternal(x, y, eventTime); if (!sShouldHandleGesture) { return; } - // A gesture should start only from the letter key. + // A gesture should start only from a non-modifier key. mIsDetectingGesture = (mKeyboard != null) && mKeyboard.mId.isAlphabetKeyboard() - && !mIsShowingMoreKeysPanel && key != null && Keyboard.isLetterCode(key.mCode); + && !mIsShowingMoreKeysPanel && key != null && !key.isModifier(); if (mIsDetectingGesture) { if (getActivePointerTrackerCount() == 1) { sGestureFirstDownTime = eventTime; @@ -827,7 +841,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { || (key != null && key.isModifier()) || mKeyDetector.alwaysAllowsSlidingInput(); mKeyboardLayoutHasBeenChanged = false; - mKeyAlreadyProcessed = false; + mIsTrackingCanceled = false; resetSlidingKeyInput(); if (key != null) { // This onPress call may have changed keyboard layout. Those cases are detected at @@ -859,7 +873,17 @@ public final class PointerTracker implements PointerTrackerQueue.Element { final boolean isMajorEvent, final Key key) { final int gestureTime = (int)(eventTime - sGestureFirstDownTime); if (mIsDetectingGesture) { - mGestureStrokeWithPreviewPoints.addPoint(x, y, gestureTime, isMajorEvent); + final boolean onValidArea = mGestureStrokeWithPreviewPoints.addPointOnKeyboard( + x, y, gestureTime, isMajorEvent); + if (!onValidArea) { + sPointerTrackerQueue.cancelAllPointerTracker(); + if (DEBUG_LISTENER) { + Log.d(TAG, String.format("[%d] onCancelBatchInput: batchPoints=%d", + mPointerId, sAggregratedPointers.getPointerSize())); + } + mListener.onCancelBatchInput(); + return; + } mayStartBatchInput(key); if (sInGesture) { mayUpdateBatchInput(eventTime, key); @@ -871,7 +895,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { if (DEBUG_MOVE_EVENT) { printTouchEvent("onMoveEvent:", x, y, eventTime); } - if (mKeyAlreadyProcessed) { + if (mIsTrackingCanceled) { return; } @@ -891,136 +915,150 @@ public final class PointerTracker implements PointerTrackerQueue.Element { onMoveEventInternal(x, y, eventTime); } + private void processSlidingKeyInput(final Key newKey, final int x, final int y, + final long eventTime) { + // This onPress call may have changed keyboard layout. Those cases are detected + // at {@link #setKeyboard}. In those cases, we should update key according + // to the new keyboard layout. + Key key = newKey; + if (callListenerOnPressAndCheckKeyboardLayoutChange(key)) { + key = onMoveKey(x, y); + } + onMoveToNewKey(key, x, y); + startLongPressTimer(key); + setPressedKeyGraphics(key, eventTime); + } + + private void processPhantomSuddenMoveHack(final Key key, final int x, final int y, + final long eventTime, final Key oldKey, final int lastX, final int lastY) { + if (DEBUG_MODE) { + Log.w(TAG, String.format("[%d] onMoveEvent:" + + " phantom sudden move event (distance=%d) is translated to " + + "up[%d,%d,%s]/down[%d,%d,%s] events", mPointerId, + getDistance(x, y, lastX, lastY), + lastX, lastY, Constants.printableCode(oldKey.mCode), + x, y, Constants.printableCode(key.mCode))); + } + // TODO: This should be moved to outside of this nested if-clause? + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_onMoveEvent(x, y, lastX, lastY); + } + onUpEventInternal(eventTime); + onDownEventInternal(x, y, eventTime); + } + + private void processProximateBogusDownMoveUpEventHack(final Key key, final int x, final int y, + final long eventTime, final Key oldKey, final int lastX, final int lastY) { + if (DEBUG_MODE) { + final float keyDiagonal = (float)Math.hypot( + mKeyboard.mMostCommonKeyWidth, mKeyboard.mMostCommonKeyHeight); + final float radiusRatio = + mBogusMoveEventDetector.getDistanceFromDownEvent(x, y) + / keyDiagonal; + Log.w(TAG, String.format("[%d] onMoveEvent:" + + " bogus down-move-up event (raidus=%.2f key diagonal) is " + + " translated to up[%d,%d,%s]/down[%d,%d,%s] events", + mPointerId, radiusRatio, + lastX, lastY, Constants.printableCode(oldKey.mCode), + x, y, Constants.printableCode(key.mCode))); + } + onUpEventInternal(eventTime); + onDownEventInternal(x, y, eventTime); + } + + private void processSildeOutFromOldKey(final Key oldKey) { + setReleasedKeyGraphics(oldKey); + callListenerOnRelease(oldKey, oldKey.mCode, true); + startSlidingKeyInput(oldKey); + mTimerProxy.cancelKeyTimers(); + } + + private void slideFromOldKeyToNewKey(final Key key, final int x, final int y, + final long eventTime, final Key oldKey, final int lastX, final int lastY) { + // The pointer has been slid in to the new key from the previous key, we must call + // onRelease() first to notify that the previous key has been released, then call + // onPress() to notify that the new key is being pressed. + processSildeOutFromOldKey(oldKey); + startRepeatKey(key); + if (mIsAllowedSlidingKeyInput) { + processSlidingKeyInput(key, x, y, eventTime); + } + // HACK: On some devices, quick successive touches may be reported as a sudden move by + // touch panel firmware. This hack detects such cases and translates the move event to + // successive up and down events. + // TODO: Should find a way to balance gesture detection and this hack. + else if (sNeedsPhantomSuddenMoveEventHack + && getDistance(x, y, lastX, lastY) >= mPhantonSuddenMoveThreshold) { + processPhantomSuddenMoveHack(key, x, y, eventTime, oldKey, lastX, lastY); + } + // HACK: On some devices, quick successive proximate touches may be reported as a bogus + // down-move-up event by touch panel firmware. This hack detects such cases and breaks + // these events into separate up and down events. + else if (sNeedsProximateBogusDownMoveUpEventHack && sTimeRecorder.isInFastTyping(eventTime) + && mBogusMoveEventDetector.isCloseToActualDownEvent(x, y)) { + processProximateBogusDownMoveUpEventHack(key, x, y, eventTime, oldKey, lastX, lastY); + } + // HACK: If there are currently multiple touches, register the key even if the finger + // slides off the key. This defends against noise from some touch panels when there are + // close multiple touches. + // Caveat: When in chording input mode with a modifier key, we don't use this hack. + else if (getActivePointerTrackerCount() > 1 + && !sPointerTrackerQueue.hasModifierKeyOlderThan(this)) { + if (DEBUG_MODE) { + Log.w(TAG, String.format("[%d] onMoveEvent:" + + " detected sliding finger while multi touching", mPointerId)); + } + onUpEvent(x, y, eventTime); + cancelTracking(); + setReleasedKeyGraphics(oldKey); + } else { + if (!mIsDetectingGesture) { + cancelTracking(); + } + setReleasedKeyGraphics(oldKey); + } + } + + private void slideOutFromOldKey(final Key oldKey, final int x, final int y) { + // The pointer has been slid out from the previous key, we must call onRelease() to + // notify that the previous key has been released. + processSildeOutFromOldKey(oldKey); + if (mIsAllowedSlidingKeyInput) { + onMoveToNewKey(null, x, y); + } else { + if (!mIsDetectingGesture) { + cancelTracking(); + } + } + } + private void onMoveEventInternal(final int x, final int y, final long eventTime) { final int lastX = mLastX; final int lastY = mLastY; final Key oldKey = mCurrentKey; - Key key = onMoveKey(x, y); + final Key newKey = onMoveKey(x, y); if (sShouldHandleGesture) { // Register move event on gesture tracker. - onGestureMoveEvent(x, y, eventTime, true /* isMajorEvent */, key); + onGestureMoveEvent(x, y, eventTime, true /* isMajorEvent */, newKey); if (sInGesture) { - mTimerProxy.cancelLongPressTimer(); mCurrentKey = null; setReleasedKeyGraphics(oldKey); return; } } - if (key != null) { - if (oldKey == null) { + if (newKey != null) { + if (oldKey != null && isMajorEnoughMoveToBeOnNewKey(x, y, eventTime, newKey)) { + slideFromOldKeyToNewKey(newKey, x, y, eventTime, oldKey, lastX, lastY); + } else if (oldKey == null) { // The pointer has been slid in to the new key, but the finger was not on any keys. // In this case, we must call onPress() to notify that the new key is being pressed. - // This onPress call may have changed keyboard layout. Those cases are detected at - // {@link #setKeyboard}. In those cases, we should update key according to the - // new keyboard layout. - if (callListenerOnPressAndCheckKeyboardLayoutChange(key)) { - key = onMoveKey(x, y); - } - onMoveToNewKey(key, x, y); - startLongPressTimer(key); - setPressedKeyGraphics(key, eventTime); - } else if (isMajorEnoughMoveToBeOnNewKey(x, y, eventTime, key)) { - // The pointer has been slid in to the new key from the previous key, we must call - // onRelease() first to notify that the previous key has been released, then call - // onPress() to notify that the new key is being pressed. - setReleasedKeyGraphics(oldKey); - callListenerOnRelease(oldKey, oldKey.mCode, true); - startSlidingKeyInput(oldKey); - mTimerProxy.cancelKeyTimers(); - startRepeatKey(key); - if (mIsAllowedSlidingKeyInput) { - // This onPress call may have changed keyboard layout. Those cases are detected - // at {@link #setKeyboard}. In those cases, we should update key according - // to the new keyboard layout. - if (callListenerOnPressAndCheckKeyboardLayoutChange(key)) { - key = onMoveKey(x, y); - } - onMoveToNewKey(key, x, y); - startLongPressTimer(key); - setPressedKeyGraphics(key, eventTime); - } else { - // HACK: On some devices, quick successive touches may be reported as a sudden - // move by touch panel firmware. This hack detects such cases and translates the - // move event to successive up and down events. - // TODO: Should find a way to balance gesture detection and this hack. - if (sNeedsPhantomSuddenMoveEventHack - && getDistance(x, y, lastX, lastY) >= mPhantonSuddenMoveThreshold) { - if (DEBUG_MODE) { - Log.w(TAG, String.format("[%d] onMoveEvent:" - + " phantom sudden move event (distance=%d) is translated to " - + "up[%d,%d,%s]/down[%d,%d,%s] events", mPointerId, - getDistance(x, y, lastX, lastY), - lastX, lastY, Keyboard.printableCode(oldKey.mCode), - x, y, Keyboard.printableCode(key.mCode))); - } - // TODO: This should be moved to outside of this nested if-clause? - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.pointerTracker_onMoveEvent(x, y, lastX, lastY); - } - onUpEventInternal(eventTime); - onDownEventInternal(x, y, eventTime); - } - // HACK: On some devices, quick successive proximate touches may be reported as - // a bogus down-move-up event by touch panel firmware. This hack detects such - // cases and breaks these events into separate up and down events. - else if (sNeedsProximateBogusDownMoveUpEventHack - && sTimeRecorder.isInFastTyping(eventTime) - && mBogusMoveEventDetector.isCloseToActualDownEvent(x, y)) { - if (DEBUG_MODE) { - final float keyDiagonal = (float)Math.hypot( - mKeyboard.mMostCommonKeyWidth, mKeyboard.mMostCommonKeyHeight); - final float radiusRatio = - mBogusMoveEventDetector.getDistanceFromDownEvent(x, y) - / keyDiagonal; - Log.w(TAG, String.format("[%d] onMoveEvent:" - + " bogus down-move-up event (raidus=%.2f key diagonal) is " - + " translated to up[%d,%d,%s]/down[%d,%d,%s] events", - mPointerId, radiusRatio, - lastX, lastY, Keyboard.printableCode(oldKey.mCode), - x, y, Keyboard.printableCode(key.mCode))); - } - onUpEventInternal(eventTime); - onDownEventInternal(x, y, eventTime); - } else { - // HACK: If there are currently multiple touches, register the key even if - // the finger slides off the key. This defends against noise from some - // touch panels when there are close multiple touches. - // Caveat: When in chording input mode with a modifier key, we don't use - // this hack. - if (getActivePointerTrackerCount() > 1 && sPointerTrackerQueue != null - && !sPointerTrackerQueue.hasModifierKeyOlderThan(this)) { - if (DEBUG_MODE) { - Log.w(TAG, String.format("[%d] onMoveEvent:" - + " detected sliding finger while multi touching", - mPointerId)); - } - onUpEvent(x, y, eventTime); - mKeyAlreadyProcessed = true; - } - if (!mIsDetectingGesture) { - mKeyAlreadyProcessed = true; - } - setReleasedKeyGraphics(oldKey); - } - } + processSlidingKeyInput(newKey, x, y, eventTime); } - } else { - if (oldKey != null && isMajorEnoughMoveToBeOnNewKey(x, y, eventTime, key)) { - // The pointer has been slid out from the previous key, we must call onRelease() to - // notify that the previous key has been released. - setReleasedKeyGraphics(oldKey); - callListenerOnRelease(oldKey, oldKey.mCode, true); - startSlidingKeyInput(oldKey); - mTimerProxy.cancelLongPressTimer(); - if (mIsAllowedSlidingKeyInput) { - onMoveToNewKey(key, x, y); - } else { - if (!mIsDetectingGesture) { - mKeyAlreadyProcessed = true; - } - } + } else { // newKey == null + if (oldKey != null && isMajorEnoughMoveToBeOnNewKey(x, y, eventTime, newKey)) { + slideOutFromOldKey(oldKey, x, y); } } } @@ -1030,22 +1068,17 @@ public final class PointerTracker implements PointerTrackerQueue.Element { printTouchEvent("onUpEvent :", x, y, eventTime); } - final PointerTrackerQueue queue = sPointerTrackerQueue; - if (queue != null) { - if (!sInGesture) { - if (mCurrentKey != null && mCurrentKey.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); - } + if (!sInGesture) { + if (mCurrentKey != null && mCurrentKey.isModifier()) { + // Before processing an up event of modifier key, all pointers already being + // tracked should be released. + sPointerTrackerQueue.releaseAllPointersExcept(this, eventTime); + } else { + sPointerTrackerQueue.releaseAllPointersOlderThan(this, eventTime); } } onUpEventInternal(eventTime); - if (queue != null) { - queue.remove(this); - } + sPointerTrackerQueue.remove(this); } // Let this pointer tracker know that one of newer-than-this pointer trackers got an up event. @@ -1057,7 +1090,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { printTouchEvent("onPhntEvent:", getLastX(), getLastY(), eventTime); } onUpEventInternal(eventTime); - mKeyAlreadyProcessed = true; + cancelTracking(); } private void onUpEventInternal(final long eventTime) { @@ -1081,7 +1114,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { return; } - if (mKeyAlreadyProcessed) { + if (mIsTrackingCanceled) { return; } if (currentKey != null && !currentKey.isRepeatable()) { @@ -1095,13 +1128,15 @@ public final class PointerTracker implements PointerTrackerQueue.Element { onDownEvent(x, y, SystemClock.uptimeMillis(), handler); } + @Override + public void cancelTracking() { + mIsTrackingCanceled = true; + } + public void onLongPressed() { - mKeyAlreadyProcessed = true; + cancelTracking(); setReleasedKeyGraphics(mCurrentKey); - final PointerTrackerQueue queue = sPointerTrackerQueue; - if (queue != null) { - queue.remove(this); - } + sPointerTrackerQueue.remove(this); } public void onCancelEvent(final int x, final int y, final long eventTime) { @@ -1109,11 +1144,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element { printTouchEvent("onCancelEvt:", x, y, eventTime); } - final PointerTrackerQueue queue = sPointerTrackerQueue; - if (queue != null) { - queue.releaseAllPointersExcept(this, eventTime); - queue.remove(this); - } + sPointerTrackerQueue.releaseAllPointersExcept(this, eventTime); + sPointerTrackerQueue.remove(this); onCancelEventInternal(); } @@ -1149,38 +1181,38 @@ public final class PointerTracker implements PointerTrackerQueue.Element { final Key curKey = mCurrentKey; if (newKey == curKey) { return false; - } else if (curKey != null) { - final int keyHysteresisDistanceSquared = mKeyDetector.getKeyHysteresisDistanceSquared( - mIsInSlidingKeyInputFromModifier); - final int distanceFromKeyEdgeSquared = curKey.squaredDistanceToEdge(x, y); - if (distanceFromKeyEdgeSquared >= keyHysteresisDistanceSquared) { - if (DEBUG_MODE) { - final float distanceToEdgeRatio = (float)Math.sqrt(distanceFromKeyEdgeSquared) - / mKeyboard.mMostCommonKeyWidth; - Log.d(TAG, String.format("[%d] isMajorEnoughMoveToBeOnNewKey:" - +" %.2f key width from key edge", - mPointerId, distanceToEdgeRatio)); - } - return true; + } + if (curKey == null /* && newKey != null */) { + return true; + } + // Here curKey points to the different key from newKey. + final int keyHysteresisDistanceSquared = mKeyDetector.getKeyHysteresisDistanceSquared( + mIsInSlidingKeyInputFromModifier); + final int distanceFromKeyEdgeSquared = curKey.squaredDistanceToEdge(x, y); + if (distanceFromKeyEdgeSquared >= keyHysteresisDistanceSquared) { + if (DEBUG_MODE) { + final float distanceToEdgeRatio = (float)Math.sqrt(distanceFromKeyEdgeSquared) + / mKeyboard.mMostCommonKeyWidth; + Log.d(TAG, String.format("[%d] isMajorEnoughMoveToBeOnNewKey:" + +" %.2f key width from key edge", mPointerId, distanceToEdgeRatio)); } - if (sNeedsProximateBogusDownMoveUpEventHack && !mIsAllowedSlidingKeyInput - && sTimeRecorder.isInFastTyping(eventTime) - && mBogusMoveEventDetector.hasTraveledLongDistance(x, y)) { - if (DEBUG_MODE) { - final float keyDiagonal = (float)Math.hypot( - mKeyboard.mMostCommonKeyWidth, mKeyboard.mMostCommonKeyHeight); - final float lengthFromDownRatio = - mBogusMoveEventDetector.mAccumulatedDistanceFromDownKey / keyDiagonal; - Log.d(TAG, String.format("[%d] isMajorEnoughMoveToBeOnNewKey:" - + " %.2f key diagonal from virtual down point", - mPointerId, lengthFromDownRatio)); - } - return true; + return true; + } + if (sNeedsProximateBogusDownMoveUpEventHack && !mIsAllowedSlidingKeyInput + && sTimeRecorder.isInFastTyping(eventTime) + && mBogusMoveEventDetector.hasTraveledLongDistance(x, y)) { + if (DEBUG_MODE) { + final float keyDiagonal = (float)Math.hypot( + mKeyboard.mMostCommonKeyWidth, mKeyboard.mMostCommonKeyHeight); + final float lengthFromDownRatio = + mBogusMoveEventDetector.mAccumulatedDistanceFromDownKey / keyDiagonal; + Log.d(TAG, String.format("[%d] isMajorEnoughMoveToBeOnNewKey:" + + " %.2f key diagonal from virtual down point", + mPointerId, lengthFromDownRatio)); } - return false; - } else { // curKey == null && newKey != null return true; } + return false; } private void startLongPressTimer(final Key key) { @@ -1205,6 +1237,6 @@ public final class PointerTracker implements PointerTrackerQueue.Element { final Key key = mKeyDetector.detectHitKey(x, y); final String code = KeyDetector.printableCode(key); Log.d(TAG, String.format("[%d]%s%s %4d %4d %5d %s", mPointerId, - (mKeyAlreadyProcessed ? "-" : " "), title, x, y, eventTime, code)); + (mIsTrackingCanceled ? "-" : " "), title, x, y, eventTime, code)); } } |