diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 437bbf06ba7c0b6579ef62262027b2825a1474ed..4f6af98cade28741c8f2b4045dcd0372ab275280 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -23,7 +23,6 @@ import android.view.View; import android.widget.TextView; import com.android.inputmethod.keyboard.internal.GestureStroke; -import com.android.inputmethod.keyboard.internal.GestureTracker; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.latin.InputPointers; import com.android.inputmethod.latin.LatinImeLogger; @@ -39,6 +38,10 @@ public class PointerTracker { private static final boolean DEBUG_LISTENER = false; private static boolean DEBUG_MODE = LatinImeLogger.sDBG; + // TODO: There should be an option to turn on/off the gesture input. + private static final boolean GESTURE_ON = true; + private static final int MIN_RECOGNITION_TIME = 100; // msec + public interface KeyEventHandler { /** * Get KeyDetector object that is used for this PointerTracker. @@ -128,6 +131,13 @@ public class PointerTracker { private int mKeyQuarterWidthSquared; private final TextView mKeyPreviewText; + private boolean mIsAlphabetKeyboard; + private boolean mIsPossibleGesture = false; + private boolean mInGesture = false; + + private int mLastRecognitionPointSize = 0; + private long mLastRecognitionTime = 0; + // The position and time at which first down event occurred. private long mDownTime; private long mUpTime; @@ -164,9 +174,6 @@ public class PointerTracker { private static final KeyboardActionListener EMPTY_LISTENER = new KeyboardActionListener.Adapter(); - // Gesture tracker singleton instance - private static final GestureTracker sGestureTracker = GestureTracker.getInstance(); - private final GestureStroke mGestureStroke; public static void init(boolean hasDistinctMultitouch, @@ -207,7 +214,6 @@ public class PointerTracker { for (final PointerTracker tracker : sTrackers) { tracker.mListener = listener; } - GestureTracker.init(listener); } public static void setKeyDetector(KeyDetector keyDetector) { @@ -216,7 +222,6 @@ public class PointerTracker { // Mark that keyboard layout has been changed. tracker.mKeyboardLayoutHasBeenChanged = true; } - sGestureTracker.setKeyboard(keyDetector.getKeyboard()); } public static void dismissAllKeyPreviews() { @@ -226,35 +231,35 @@ public class PointerTracker { } } - // The working and returning object of the following methods, - // {@link #getIncrementalBatchPoints()} and {@link #getAllBatchPoints()}. - private static final InputPointers mAggregatedPointers = new InputPointers(); - - // TODO: This method is called only from GestureTracker and should address the thread-safty - // issue soon. - public static InputPointers getIncrementalBatchPoints() { - final InputPointers pointers = mAggregatedPointers; - pointers.reset(); + // TODO: To handle multi-touch gestures we may want to move this method to + // {@link PointerTrackerQueue}. + private static InputPointers getIncrementalBatchPoints() { + final InputPointers pointers = new InputPointers(); + // TODO: Add a default capacity parameter for the InputPointers' constructor. + // TODO: Avoid creating a new instance here? for (final PointerTracker tracker : sTrackers) { - tracker.getGestureStroke().appendIncrementalBatchPoints(pointers); + tracker.mGestureStroke.appendIncrementalBatchPoints(pointers); } return pointers; } - // TODO: This method is called only from GestureTracker and should address the thread-safety - // issue soon. - public static InputPointers getAllBatchPoints() { - final InputPointers pointers = mAggregatedPointers; - pointers.reset(); + // TODO: To handle multi-touch gestures we may want to move this method to + // {@link PointerTrackerQueue}. + private static InputPointers getAllBatchPoints() { + // TODO: Add a default capacity parameter for the InputPointers' constructor. + // TODO: Avoid creating a new instance here? + final InputPointers pointers = new InputPointers(); for (final PointerTracker tracker : sTrackers) { - tracker.getGestureStroke().appendAllBatchPoints(pointers); + tracker.mGestureStroke.appendAllBatchPoints(pointers); } return pointers; } + // TODO: To handle multi-touch gestures we may want to move this method to + // {@link PointerTrackerQueue}. public static void clearBatchInputPoints() { for (final PointerTracker tracker : sTrackers) { - tracker.getGestureStroke().reset(); + tracker.mGestureStroke.reset(); } } @@ -274,13 +279,9 @@ public class PointerTracker { return mKeyPreviewText; } - public GestureStroke getGestureStroke() { - return mGestureStroke; - } - // Returns true if keyboard has been changed by this callback. private boolean callListenerOnPressAndCheckKeyboardLayoutChange(Key key) { - if (sGestureTracker.isInGesture()) { + if (mInGesture) { return false; } final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier(); @@ -336,7 +337,7 @@ public class PointerTracker { // Note that we need primaryCode argument because the keyboard may in shifted state and the // primaryCode is different from {@link Key#mCode}. private void callListenerOnRelease(Key key, int primaryCode, boolean withSliding) { - if (sGestureTracker.isInGesture()) { + if (mInGesture) { return; } final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier(); @@ -369,6 +370,7 @@ public class PointerTracker { private void setKeyDetectorInner(KeyDetector keyDetector) { mKeyDetector = keyDetector; mKeyboard = keyDetector.getKeyboard(); + mIsAlphabetKeyboard = mKeyboard.mId.isAlphabetKeyboard(); mGestureStroke.setGestureSampleLength( mKeyboard.mMostCommonKeyWidth, mKeyboard.mMostCommonKeyHeight); final Key newKey = mKeyDetector.detectHitKey(mKeyX, mKeyY); @@ -441,7 +443,7 @@ public class PointerTracker { return; } - if (!key.noKeyPreview() && !sGestureTracker.isInGesture()) { + if (!key.noKeyPreview() && !mInGesture) { mDrawingProxy.showKeyPreview(this); } updatePressKeyGraphics(key); @@ -512,6 +514,45 @@ public class PointerTracker { return newKey; } + private void startBatchInput() { + if (DEBUG_LISTENER) { + Log.d(TAG, "onStartBatchInput"); + } + mInGesture = true; + mListener.onStartBatchInput(); + } + + private void updateBatchInput(InputPointers batchPoints) { + if (DEBUG_LISTENER) { + Log.d(TAG, "onUpdateBatchInput: batchPoints=" + batchPoints.getPointerSize()); + } + mListener.onUpdateBatchInput(batchPoints); + } + + private void endBatchInput(InputPointers batchPoints) { + if (DEBUG_LISTENER) { + Log.d(TAG, "onEndBatchInput: batchPoints=" + batchPoints.getPointerSize()); + } + mListener.onEndBatchInput(batchPoints); + mInGesture = false; + clearBatchInputPoints(); + } + + private void abortBatchInput() { + mIsPossibleGesture = false; + mInGesture = false; + } + + private boolean updateBatchInputRecognitionState(long eventTime, int size) { + if (size > mLastRecognitionPointSize + && eventTime > mLastRecognitionTime + MIN_RECOGNITION_TIME) { + mLastRecognitionPointSize = size; + mLastRecognitionTime = eventTime; + return true; + } + return false; + } + public void processMotionEvent(int action, int x, int y, long eventTime, KeyEventHandler handler) { switch (action) { @@ -570,7 +611,13 @@ public class PointerTracker { } onDownEventInternal(x, y, eventTime); if (queue != null && queue.size() == 1) { - sGestureTracker.onDownEvent(this, x, y, eventTime, key); + mIsPossibleGesture = false; + // A gesture should start only from the letter key. + if (GESTURE_ON && mIsAlphabetKeyboard && key != null + && Keyboard.isLetterCode(key.mCode)) { + mIsPossibleGesture = true; + mGestureStroke.addPoint(x, y, 0, false); + } } } @@ -606,6 +653,25 @@ public class PointerTracker { mIsInSlidingKeyInput = true; } + private void onGestureMoveEvent(PointerTracker tracker, int x, int y, long eventTime, + boolean isHistorical, Key key) { + final int gestureTime = (int)(eventTime - tracker.getDownTime()); + if (GESTURE_ON && mIsPossibleGesture) { + final GestureStroke stroke = mGestureStroke; + stroke.addPoint(x, y, gestureTime, isHistorical); + if (!mInGesture && stroke.isStartOfAGesture(gestureTime)) { + startBatchInput(); + } + } + + if (key != null && mInGesture) { + final InputPointers batchPoints = getIncrementalBatchPoints(); + if (updateBatchInputRecognitionState(eventTime, batchPoints.getPointerSize())) { + updateBatchInput(batchPoints); + } + } + } + public void onMoveEvent(int x, int y, long eventTime, MotionEvent me) { if (DEBUG_MOVE_EVENT) printTouchEvent("onMoveEvent:", x, y, eventTime); @@ -620,7 +686,7 @@ public class PointerTracker { final int historicalX = (int)me.getHistoricalX(pointerIndex, h); final int historicalY = (int)me.getHistoricalY(pointerIndex, h); final long historicalTime = me.getHistoricalEventTime(h); - sGestureTracker.onMoveEvent(this, historicalX, historicalY, historicalTime, + onGestureMoveEvent(this, historicalX, historicalY, historicalTime, true /* isHistorical */, null); } } @@ -631,8 +697,8 @@ public class PointerTracker { Key key = onMoveKey(x, y); // Register move event on gesture tracker. - sGestureTracker.onMoveEvent(this, x, y, eventTime, false, key); - if (sGestureTracker.isInGesture()) { + onGestureMoveEvent(this, x, y, eventTime, false /* isHistorical */, key); + if (mInGesture) { mIgnoreModifierKey = true; mTimerProxy.cancelLongPressTimer(); mIsInSlidingKeyInput = true; @@ -729,7 +795,7 @@ public class PointerTracker { final PointerTrackerQueue queue = sPointerTrackerQueue; if (queue != null) { - if (!sGestureTracker.isInGesture()) { + if (!mInGesture) { if (mCurrentKey != null && mCurrentKey.isModifier()) { // Before processing an up event of modifier key, all pointers already being // tracked should be released. @@ -763,21 +829,16 @@ public class PointerTracker { mIsShowingMoreKeysPanel = false; } - if (sGestureTracker.isInGesture()) { + if (mInGesture) { // Register up event on gesture tracker. - sGestureTracker.onUpEvent(this, x, y, eventTime); - if (!sPointerTrackerQueue.isAnyInSlidingKeyInput()) { - // TODO: Calls to beginBatchInput() is missing in this class. Reorganize the code. - sGestureTracker.endBatchInput(); - } + // TODO: Figure out how to deal with multiple fingers that are in gesture, sliding, + // and/or tapping mode? + endBatchInput(getAllBatchPoints()); if (mCurrentKey != null) { callListenerOnRelease(mCurrentKey, mCurrentKey.mCode, true); + mCurrentKey = null; } - mCurrentKey = null; return; - } else { - // TODO: Calls to beginBatchInput() is missing in this class. Reorganize the code. - sGestureTracker.endBatchInput(); } if (mKeyAlreadyProcessed) @@ -791,8 +852,7 @@ public class PointerTracker { onLongPressed(); onDownEvent(x, y, SystemClock.uptimeMillis(), handler); mIsShowingMoreKeysPanel = true; - // TODO: Calls to beginBatchInput() is missing in this class. Reorganize the code. - sGestureTracker.abortBatchInput(); + abortBatchInput(); } public void onLongPressed() { @@ -827,7 +887,7 @@ public class PointerTracker { } private void startRepeatKey(Key key) { - if (key != null && key.isRepeatable() && !sGestureTracker.isInGesture()) { + if (key != null && key.isRepeatable() && !mInGesture) { onRegisterKey(key); mTimerProxy.startKeyRepeatTimer(this); } @@ -857,7 +917,7 @@ public class PointerTracker { } private void startLongPressTimer(Key key) { - if (key != null && key.isLongPressEnabled() && !sGestureTracker.isInGesture()) { + if (key != null && key.isLongPressEnabled() && !mInGesture) { mTimerProxy.startLongPressTimer(this); } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureTracker.java b/java/src/com/android/inputmethod/keyboard/internal/GestureTracker.java deleted file mode 100644 index fbfa663324610687acc432bcdeb20d022bfaa8c3..0000000000000000000000000000000000000000 --- a/java/src/com/android/inputmethod/keyboard/internal/GestureTracker.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.android.inputmethod.keyboard.internal; - -import android.util.Log; - -import com.android.inputmethod.keyboard.Key; -import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.keyboard.KeyboardActionListener; -import com.android.inputmethod.keyboard.PointerTracker; -import com.android.inputmethod.latin.InputPointers; - -// TODO: Remove this class by consolidating with PointerTracker -public class GestureTracker { - private static final String TAG = GestureTracker.class.getSimpleName(); - private static final boolean DEBUG_LISTENER = false; - - // TODO: There should be an option to turn on/off the gesture input. - private static final boolean GESTURE_ON = true; - - private static final GestureTracker sInstance = new GestureTracker(); - - private static final int MIN_RECOGNITION_TIME = 100; - - private boolean mIsAlphabetKeyboard; - private boolean mIsPossibleGesture = false; - private boolean mInGesture = false; - - private KeyboardActionListener mListener; - - private int mLastRecognitionPointSize = 0; - private long mLastRecognitionTime = 0; - - public static void init(KeyboardActionListener listner) { - sInstance.mListener = listner; - } - - public static GestureTracker getInstance() { - return sInstance; - } - - private GestureTracker() { - } - - public void setKeyboard(Keyboard keyboard) { - mIsAlphabetKeyboard = keyboard.mId.isAlphabetKeyboard(); - } - - private void startBatchInput() { - if (DEBUG_LISTENER) { - Log.d(TAG, "onStartBatchInput"); - } - mInGesture = true; - mListener.onStartBatchInput(); - } - - // TODO: The corresponding startBatchInput() is a private method. Reorganize the code. - public void endBatchInput() { - if (isInGesture()) { - final InputPointers batchPoints = PointerTracker.getAllBatchPoints(); - if (DEBUG_LISTENER) { - Log.d(TAG, "onEndBatchInput: batchPoints=" + batchPoints.getPointerSize()); - } - mListener.onEndBatchInput(batchPoints); - } - mInGesture = false; - clearBatchInputPoints(); - } - - public void abortBatchInput() { - mIsPossibleGesture = false; - mInGesture = false; - } - - public boolean isInGesture() { - return mInGesture; - } - - public void onDownEvent(PointerTracker tracker, int x, int y, long eventTime, Key key) { - mIsPossibleGesture = false; - // A gesture should start only from the letter key. - if (GESTURE_ON && mIsAlphabetKeyboard && key != null && Keyboard.isLetterCode(key.mCode)) { - mIsPossibleGesture = true; - tracker.getGestureStroke().addPoint(x, y, 0, false); - } - } - - public void onMoveEvent(PointerTracker tracker, int x, int y, long eventTime, - boolean isHistorical, Key key) { - final int gestureTime = (int)(eventTime - tracker.getDownTime()); - if (GESTURE_ON && mIsPossibleGesture) { - final GestureStroke stroke = tracker.getGestureStroke(); - stroke.addPoint(x, y, gestureTime, isHistorical); - if (!isInGesture() && stroke.isStartOfAGesture(gestureTime)) { - startBatchInput(); - } - } - - if (key != null && isInGesture()) { - final InputPointers batchPoints = PointerTracker.getIncrementalBatchPoints(); - if (updateBatchInputRecognitionState(eventTime, batchPoints.getPointerSize())) { - if (DEBUG_LISTENER) { - Log.d(TAG, "onUpdateBatchInput: batchPoints=" + batchPoints.getPointerSize()); - } - mListener.onUpdateBatchInput(batchPoints); - } - } - } - - public void onUpEvent(PointerTracker tracker, int x, int y, long eventTime) { - if (isInGesture()) { - final InputPointers batchPoints = PointerTracker.getAllBatchPoints(); - if (DEBUG_LISTENER) { - Log.d(TAG, "onUpdateBatchInput: batchPoints=" + batchPoints.getPointerSize()); - } - mListener.onUpdateBatchInput(batchPoints); - } - } - - private void clearBatchInputPoints() { - PointerTracker.clearBatchInputPoints(); - mLastRecognitionPointSize = 0; - mLastRecognitionTime = 0; - } - - private boolean updateBatchInputRecognitionState(long eventTime, int size) { - if (size > mLastRecognitionPointSize - && eventTime > mLastRecognitionTime + MIN_RECOGNITION_TIME) { - mLastRecognitionPointSize = size; - mLastRecognitionTime = eventTime; - return true; - } - return false; - } -} diff --git a/java/src/com/android/inputmethod/latin/InputPointers.java b/java/src/com/android/inputmethod/latin/InputPointers.java index 5ad53480fc4264472c7f985382e91edcfdad531e..298e2b213cf9616edd5fec70d42c9e0741cf911e 100644 --- a/java/src/com/android/inputmethod/latin/InputPointers.java +++ b/java/src/com/android/inputmethod/latin/InputPointers.java @@ -60,6 +60,9 @@ public class InputPointers { * @param length the number of pointers to be appended. */ public void append(InputPointers src, int startPos, int length) { + if (length == 0) { + return; + } mXCoordinates.append(src.mXCoordinates, startPos, length); mYCoordinates.append(src.mYCoordinates, startPos, length); mPointerIds.append(src.mPointerIds, startPos, length);