diff options
Diffstat (limited to 'java/src/com/android/inputmethod/keyboard/PointerTracker.java')
-rw-r--r-- | java/src/com/android/inputmethod/keyboard/PointerTracker.java | 153 |
1 files changed, 106 insertions, 47 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index c7b096430..ab5fee99d 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -34,6 +34,7 @@ import com.android.inputmethod.latin.InputPointers; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.define.ProductionFlag; +import com.android.inputmethod.latin.settings.Settings; import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.CoordinateUtils; import com.android.inputmethod.latin.utils.ResourceUtils; @@ -87,14 +88,14 @@ public final class PointerTracker implements PointerTrackerQueue.Element { public void dismissKeyPreview(PointerTracker tracker); public void showSlidingKeyInputPreview(PointerTracker tracker); public void dismissSlidingKeyInputPreview(); - public void showGestureTrail(PointerTracker tracker); + public void showGestureTrail(PointerTracker tracker, boolean showsFloatingPreviewText); } public interface TimerProxy { public void startTypingStateTimer(Key typedKey); public boolean isTypingState(); - public void startKeyRepeatTimer(PointerTracker tracker); - public void startLongPressTimer(PointerTracker tracker); + public void startKeyRepeatTimer(PointerTracker tracker, int delay); + public void startLongPressTimer(PointerTracker tracker, int delay); public void cancelLongPressTimer(); public void startDoubleTapShiftKeyTimer(); public void cancelDoubleTapShiftKeyTimer(); @@ -110,9 +111,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element { @Override public boolean isTypingState() { return false; } @Override - public void startKeyRepeatTimer(PointerTracker tracker) {} + public void startKeyRepeatTimer(PointerTracker tracker, int delay) {} @Override - public void startLongPressTimer(PointerTracker tracker) {} + public void startLongPressTimer(PointerTracker tracker, int delay) {} @Override public void cancelLongPressTimer() {} @Override @@ -137,6 +138,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element { public final int mTouchNoiseThresholdTime; public final int mTouchNoiseThresholdDistance; public final int mSuppressKeyPreviewAfterBatchInputDuration; + public final int mKeyRepeatStartTimeout; + public final int mKeyRepeatInterval; + public final int mLongPressShiftLockTimeout; public static final PointerTrackerParams DEFAULT = new PointerTrackerParams(); @@ -145,6 +149,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element { mTouchNoiseThresholdTime = 0; mTouchNoiseThresholdDistance = 0; mSuppressKeyPreviewAfterBatchInputDuration = 0; + mKeyRepeatStartTimeout = 0; + mKeyRepeatInterval = 0; + mLongPressShiftLockTimeout = 0; } public PointerTrackerParams(final TypedArray mainKeyboardViewAttr) { @@ -156,6 +163,12 @@ public final class PointerTracker implements PointerTrackerQueue.Element { R.styleable.MainKeyboardView_touchNoiseThresholdDistance, 0); mSuppressKeyPreviewAfterBatchInputDuration = mainKeyboardViewAttr.getInt( R.styleable.MainKeyboardView_suppressKeyPreviewAfterBatchInputDuration, 0); + mKeyRepeatStartTimeout = mainKeyboardViewAttr.getInt( + R.styleable.MainKeyboardView_keyRepeatStartTimeout, 0); + mKeyRepeatInterval = mainKeyboardViewAttr.getInt( + R.styleable.MainKeyboardView_keyRepeatInterval, 0); + mLongPressShiftLockTimeout = mainKeyboardViewAttr.getInt( + R.styleable.MainKeyboardView_longPressShiftLockTimeout, 0); } } @@ -327,6 +340,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { // the more keys panel currently being shown. equals null if no panel is active. private MoreKeysPanel mMoreKeysPanel; + private static final int MULTIPLIER_FOR_LONG_PRESS_TIMEOUT_IN_SLIDING_INPUT = 3; // true if this pointer is in a sliding key input. boolean mIsInSlidingKeyInput; // true if this pointer is in a sliding key input from a modifier key, @@ -464,6 +478,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element { mPointerId = id; mGestureStrokeWithPreviewPoints = new GestureStrokeWithPreviewPoints( id, sGestureStrokeParams, sGesturePreviewParams); + setKeyEventHandler(handler); + } + + private void setKeyEventHandler(final KeyEventHandler handler) { setKeyDetectorInner(handler.getKeyDetector()); mListener = handler.getKeyboardActionListener(); mDrawingProxy = handler.getDrawingProxy(); @@ -471,7 +489,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } // Returns true if keyboard has been changed by this callback. - private boolean callListenerOnPressAndCheckKeyboardLayoutChange(final Key key) { + private boolean callListenerOnPressAndCheckKeyboardLayoutChange(final Key key, + final boolean isRepeatKey) { // While gesture input is going on, this method should be a no-operation. But when gesture // input has been canceled, <code>sInGesture</code> and <code>mIsDetectingGesture</code> // are set to false. To keep this method is a no-operation, @@ -481,17 +500,17 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } final boolean ignoreModifierKey = mIsInSlidingKeyInput && key.isModifier(); if (DEBUG_LISTENER) { - Log.d(TAG, String.format("[%d] onPress : %s%s%s", mPointerId, + Log.d(TAG, String.format("[%d] onPress : %s%s%s%s", mPointerId, KeyDetector.printableCode(key), ignoreModifierKey ? " ignoreModifier" : "", - key.isEnabled() ? "" : " disabled")); + key.isEnabled() ? "" : " disabled", + isRepeatKey ? " repeat" : "")); } if (ignoreModifierKey) { return false; } if (key.isEnabled()) { - mListener.onPressKey(key.mCode, false /* isRepeatKey */, - getActivePointerTrackerCount() == 1); + mListener.onPressKey(key.mCode, isRepeatKey, getActivePointerTrackerCount() == 1); final boolean keyboardLayoutHasBeenChanged = mKeyboardLayoutHasBeenChanged; mKeyboardLayoutHasBeenChanged = false; mTimerProxy.startTypingStateTimer(key); @@ -602,10 +621,6 @@ public final class PointerTracker implements PointerTrackerQueue.Element { return mIsInSlidingKeyInput; } - public boolean isInSlidingKeyInputFromModifier() { - return mIsInSlidingKeyInputFromModifier; - } - public Key getKey() { return mCurrentKey; } @@ -753,7 +768,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { return sPointerTrackerQueue.size(); } - public boolean isOldestTrackerInQueue() { + private boolean isOldestTrackerInQueue() { return sPointerTrackerQueue.getOldestElement() == this; } @@ -776,7 +791,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element { dismissAllMoreKeysPanels(); } mTimerProxy.cancelLongPressTimer(); - mDrawingProxy.showGestureTrail(this); + // A gesture floating preview text will be shown at the oldest pointer/finger on the screen. + mDrawingProxy.showGestureTrail( + this, isOldestTrackerInQueue() /* showsFloatingPreviewText */); } public void updateBatchInputByTimer(final long eventTime) { @@ -792,7 +809,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element { if (mIsTrackingForActionDisabled) { return; } - mDrawingProxy.showGestureTrail(this); + // A gesture floating preview text will be shown at the oldest pointer/finger on the screen. + mDrawingProxy.showGestureTrail( + this, isOldestTrackerInQueue() /* showsFloatingPreviewText */); } private void updateBatchInput(final long eventTime) { @@ -833,7 +852,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element { if (mIsTrackingForActionDisabled) { return; } - mDrawingProxy.showGestureTrail(this); + // A gesture floating preview text will be shown at the oldest pointer/finger on the screen. + mDrawingProxy.showGestureTrail( + this, isOldestTrackerInQueue() /* showsFloatingPreviewText */); } private void cancelBatchInput() { @@ -849,8 +870,23 @@ public final class PointerTracker implements PointerTrackerQueue.Element { 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: @@ -860,24 +896,18 @@ public final class PointerTracker implements PointerTrackerQueue.Element { 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); } - mDrawingProxy = handler.getDrawingProxy(); - mTimerProxy = handler.getTimerProxy(); - setKeyboardActionListener(handler.getKeyboardActionListener()); - setKeyDetectorInner(handler.getKeyDetector()); + setKeyEventHandler(handler); // Naive up-to-down noise filter. final long deltaT = eventTime - mUpTime; if (deltaT < sParams.mTouchNoiseThresholdTime) { @@ -909,7 +939,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } // A gesture should start only from a non-modifier key. mIsDetectingGesture = (mKeyboard != null) && mKeyboard.mId.isAlphabetKeyboard() - && key != null && !key.isModifier(); + && key != null && !key.isModifier() && !key.isRepeatable(); if (mIsDetectingGesture) { if (getActivePointerTrackerCount() == 1) { sGestureFirstDownTime = eventTime; @@ -937,7 +967,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { // 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)) { + if (callListenerOnPressAndCheckKeyboardLayoutChange(key, false /* isRepeatKey */)) { key = onDownKey(x, y, eventTime); } @@ -987,7 +1017,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } } - 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); } @@ -1013,7 +1043,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element { final int translatedY = mMoreKeysPanel.translateY(y); mMoreKeysPanel.onMoveEvent(translatedX, translatedY, mPointerId, eventTime); onMoveKey(x, y); - mDrawingProxy.showSlidingKeyInputPreview(this); + if (mIsInSlidingKeyInputFromModifier) { + mDrawingProxy.showSlidingKeyInputPreview(this); + } return; } onMoveEventInternal(x, y, eventTime); @@ -1025,7 +1057,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { // at {@link #setKeyboard}. In those cases, we should update key according // to the new keyboard layout. Key key = newKey; - if (callListenerOnPressAndCheckKeyboardLayoutChange(key)) { + if (callListenerOnPressAndCheckKeyboardLayoutChange(key, false /* isRepeatKey */)) { key = onMoveKey(x, y); } onMoveToNewKey(key, x, y); @@ -1168,10 +1200,12 @@ public final class PointerTracker implements PointerTrackerQueue.Element { slideOutFromOldKey(oldKey, x, y); } } - mDrawingProxy.showSlidingKeyInputPreview(this); + if (mIsInSlidingKeyInputFromModifier) { + mDrawingProxy.showSlidingKeyInputPreview(this); + } } - 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); } @@ -1271,7 +1305,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { 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); } @@ -1292,16 +1326,6 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } } - private void startRepeatKey(final Key key) { - if (sInGesture) return; - if (key == null) return; - if (!key.isRepeatable()) return; - // Don't start key repeat when we are in sliding input mode. - if (mIsInSlidingKeyInput) return; - detectAndSendKey(key, key.mX, key.mY, SystemClock.uptimeMillis()); - mTimerProxy.startKeyRepeatTimer(this); - } - private boolean isMajorEnoughMoveToBeOnNewKey(final int x, final int y, final long eventTime, final Key newKey) { if (mKeyDetector == null) { @@ -1353,7 +1377,22 @@ public final class PointerTracker implements PointerTrackerQueue.Element { // We always need to start the long press timer if the key has its more keys regardless of // whether or not we are in the sliding input mode. if (mIsInSlidingKeyInput && key.mMoreKeys == null) return; - mTimerProxy.startLongPressTimer(this); + final int delay; + switch (key.mCode) { + case Constants.CODE_SHIFT: + delay = sParams.mLongPressShiftLockTimeout; + break; + default: + final int longpressTimeout = Settings.getInstance().getCurrent().mKeyLongpressTimeout; + if (mIsInSlidingKeyInputFromModifier) { + // We use longer timeout for sliding finger input started from the modifier key. + delay = longpressTimeout * MULTIPLIER_FOR_LONG_PRESS_TIMEOUT_IN_SLIDING_INPUT; + } else { + delay = longpressTimeout; + } + break; + } + mTimerProxy.startLongPressTimer(this, delay); } private void detectAndSendKey(final Key key, final int x, final int y, final long eventTime) { @@ -1367,6 +1406,26 @@ public final class PointerTracker implements PointerTrackerQueue.Element { callListenerOnRelease(key, code, false /* withSliding */); } + private void startRepeatKey(final Key key) { + if (sInGesture) return; + if (key == null) return; + if (!key.isRepeatable()) return; + // Don't start key repeat when we are in sliding input mode. + if (mIsInSlidingKeyInput) return; + detectAndSendKey(key, key.mX, key.mY, SystemClock.uptimeMillis()); + mTimerProxy.startKeyRepeatTimer(this, sParams.mKeyRepeatStartTimeout); + } + + public void onKeyRepeat(final int code) { + final Key key = getKey(); + if (key == null || key.mCode != code) { + return; + } + mTimerProxy.startKeyRepeatTimer(this, sParams.mKeyRepeatInterval); + callListenerOnPressAndCheckKeyboardLayoutChange(key, true /* isRepeatKey */); + callListenerOnCodeInput(key, code, mKeyX, mKeyY, SystemClock.uptimeMillis()); + } + private void printTouchEvent(final String title, final int x, final int y, final long eventTime) { final Key key = mKeyDetector.detectHitKey(x, y); |