Consolidate GestureTracker into PointerTracker
Change-Id: Ib28fae10493a9142ba4dff6cf57f52c59766b209
This commit is contained in:
parent
10102f02af
commit
9580c467f9
3 changed files with 112 additions and 196 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue