diff options
Diffstat (limited to 'java/src/com/android/inputmethod/keyboard/PointerTracker.java')
-rw-r--r-- | java/src/com/android/inputmethod/keyboard/PointerTracker.java | 263 |
1 files changed, 154 insertions, 109 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 4ceabff4c..d23fb4aad 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -18,12 +18,8 @@ package com.android.inputmethod.keyboard; import android.content.Context; import android.content.res.Resources; -import android.os.SystemClock; import android.util.Log; -import android.view.MotionEvent; -import com.android.inputmethod.keyboard.LatinKeyboardBaseView.KeyTimerHandler; -import com.android.inputmethod.keyboard.internal.PointerTrackerKeyState; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; @@ -34,12 +30,38 @@ import java.util.List; 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; private static boolean DEBUG_MODE = LatinImeLogger.sDBG; + public interface KeyEventHandler { + /** + * Get KeyDetector object that is used for this PointerTracker. + * @return the KeyDetector object that is used for this PointerTracker + */ + public KeyDetector getKeyDetector(); + + /** + * Get KeyboardActionListener object that is used to register key code and so on. + * @return the KeyboardActionListner for this PointerTracker + */ + public KeyboardActionListener getKeyboardActionListener(); + + /** + * Get DrawingProxy object that is used for this PointerTracker. + * @return the DrawingProxy object that is used for this PointerTracker + */ + public DrawingProxy getDrawingProxy(); + + /** + * Get TimerProxy object that handles key repeat and long press timer event for this + * PointerTracker. + * @return the TimerProxy object that handles key repeat and long press timer event. + */ + public TimerProxy getTimerProxy(); + } + public interface DrawingProxy { public void invalidateKey(Key key); public void showKeyPreview(int keyIndex, PointerTracker tracker); @@ -47,6 +69,14 @@ public class PointerTracker { public void dismissKeyPreview(PointerTracker tracker); } + public interface TimerProxy { + public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker); + public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker); + public void startLongPressShiftTimer(long delay, int keyIndex, PointerTracker tracker); + public void cancelLongPressTimers(); + public void cancelKeyTimers(); + } + public final int mPointerId; // Timing constants @@ -54,12 +84,12 @@ public class PointerTracker { private final int mLongPressKeyTimeout; private final int mLongPressShiftKeyTimeout; - private final DrawingProxy mDrawingProxy; - private final KeyTimerHandler mKeyTimerHandler; + private DrawingProxy mDrawingProxy; + private TimerProxy mTimerProxy; + private final PointerTrackerQueue mPointerTrackerQueue; private KeyDetector mKeyDetector; private KeyboardActionListener mListener = EMPTY_LISTENER; private final KeyboardSwitcher mKeyboardSwitcher; - private final boolean mHasDistinctMultitouch; private final boolean mConfigSlidingKeyInputEnabled; private final int mTouchNoiseThresholdMillis; @@ -69,7 +99,19 @@ public class PointerTracker { private List<Key> mKeys; private int mKeyQuarterWidthSquared; - private final PointerTrackerKeyState mKeyState; + // The position and time at which first down event occurred. + private long mDownTime; + private long mUpTime; + + // The current key index where this pointer is. + private int mKeyIndex = KeyDetector.NOT_A_KEY; + // The position where mKeyIndex was recognized for the first time. + private int mKeyX; + private int mKeyY; + + // Last pointer position. + private int mLastX; + private int mLastY; // true if keyboard layout has been changed. private boolean mKeyboardLayoutHasBeenChanged; @@ -107,21 +149,18 @@ public class PointerTracker { public void onTextInput(CharSequence text) {} @Override public void onCancelInput() {} - @Override - public void onSwipeDown() {} }; - public PointerTracker(int id, Context context, KeyTimerHandler keyTimerHandler, - KeyDetector keyDetector, DrawingProxy drawingProxy, boolean hasDistinctMultitouch) { - if (drawingProxy == null || keyTimerHandler == null || keyDetector == null) + public PointerTracker(int id, Context context, TimerProxy timerProxy, KeyDetector keyDetector, + DrawingProxy drawingProxy, PointerTrackerQueue queue) { + if (drawingProxy == null || timerProxy == null || keyDetector == null) throw new NullPointerException(); mPointerId = id; mDrawingProxy = drawingProxy; - mKeyTimerHandler = keyTimerHandler; - mKeyDetector = keyDetector; + mTimerProxy = timerProxy; + mPointerTrackerQueue = queue; // This is null for non-distinct multi-touch device. + setKeyDetectorInner(keyDetector); mKeyboardSwitcher = KeyboardSwitcher.getInstance(); - mKeyState = new PointerTrackerKeyState(keyDetector); - mHasDistinctMultitouch = hasDistinctMultitouch; final Resources res = context.getResources(); mConfigSlidingKeyInputEnabled = res.getBoolean(R.bool.config_sliding_key_input_enabled); mDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start); @@ -135,7 +174,7 @@ public class PointerTracker { mSubtypeSwitcher = SubtypeSwitcher.getInstance(); } - public void setOnKeyboardActionListener(KeyboardActionListener listener) { + public void setKeyboardActionListener(KeyboardActionListener listener) { mListener = listener; } @@ -196,15 +235,18 @@ public class PointerTracker { mListener.onCancelInput(); } - public void setKeyboard(Keyboard keyboard, KeyDetector keyDetector) { - if (keyboard == null || keyDetector == null) - throw new NullPointerException(); - mKeyboard = keyboard; - mKeys = keyboard.getKeys(); + public void setKeyDetectorInner(KeyDetector keyDetector) { mKeyDetector = keyDetector; - mKeyState.setKeyDetector(keyDetector); - final int keyQuarterWidth = keyboard.getKeyWidth() / 4; + mKeyboard = keyDetector.getKeyboard(); + mKeys = mKeyboard.getKeys(); + final int keyQuarterWidth = mKeyboard.getKeyWidth() / 4; mKeyQuarterWidthSquared = keyQuarterWidth * keyQuarterWidth; + } + + public void setKeyDetector(KeyDetector keyDetector) { + if (keyDetector == null) + throw new NullPointerException(); + setKeyDetectorInner(keyDetector); // Mark that keyboard layout has been changed. mKeyboardLayoutHasBeenChanged = true; } @@ -232,7 +274,7 @@ public class PointerTracker { } public boolean isModifier() { - return isModifierInternal(mKeyState.getKeyIndex()); + return isModifierInternal(mKeyIndex); } private boolean isOnModifierKey(int x, int y) { @@ -254,7 +296,7 @@ public class PointerTracker { } public void setReleasedKeyGraphics() { - setReleasedKeyGraphics(mKeyState.getKeyIndex()); + setReleasedKeyGraphics(mKeyIndex); } private void setReleasedKeyGraphics(int keyIndex) { @@ -273,44 +315,59 @@ public class PointerTracker { } } - 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, queue); - break; - case MotionEvent.ACTION_DOWN: - case MotionEvent.ACTION_POINTER_DOWN: - onDownEvent(x, y, eventTime, queue); - break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_POINTER_UP: - onUpEvent(x, y, eventTime, queue); - break; - case MotionEvent.ACTION_CANCEL: - onCancelEvent(x, y, eventTime, queue); - break; - } + public int getLastX() { + return mLastX; + } + + public int getLastY() { + return mLastY; } - public void onDownEvent(int x, int y, long eventTime, PointerTrackerQueue queue) { - if (ENABLE_ASSERTION) checkAssertion(queue); + public long getDownTime() { + return mDownTime; + } + + private int onDownKey(int x, int y, long eventTime) { + mDownTime = eventTime; + return onMoveToNewKey(onMoveKeyInternal(x, y), x, y); + } + + private int onMoveKeyInternal(int x, int y) { + mLastX = x; + mLastY = y; + return mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null); + } + + private int onMoveKey(int x, int y) { + return onMoveKeyInternal(x, y); + } + + private int onMoveToNewKey(int keyIndex, int x, int y) { + mKeyIndex = keyIndex; + mKeyX = x; + mKeyY = y; + return keyIndex; + } + + private int onUpKey(int x, int y, long eventTime) { + mUpTime = eventTime; + mKeyIndex = KeyDetector.NOT_A_KEY; + return onMoveKeyInternal(x, y); + } + + public void onDownEvent(int x, int y, long eventTime, KeyEventHandler handler) { if (DEBUG_EVENT) printTouchEvent("onDownEvent:", x, y, eventTime); + mDrawingProxy = handler.getDrawingProxy(); + mTimerProxy = handler.getTimerProxy(); + setKeyboardActionListener(handler.getKeyboardActionListener()); + setKeyDetectorInner(handler.getKeyDetector()); // Naive up-to-down noise filter. - final long deltaT = eventTime - mKeyState.getUpTime(); + final long deltaT = eventTime - mUpTime; if (deltaT < mTouchNoiseThresholdMillis) { - final int dx = x - mKeyState.getLastX(); - final int dy = y - mKeyState.getLastY(); + final int dx = x - mLastX; + final int dy = y - mLastY; final int distanceSquared = (dx * dx + dy * dy); if (distanceSquared < mTouchNoiseThresholdDistanceSquared) { if (DEBUG_MODE) @@ -321,6 +378,7 @@ public class PointerTracker { } } + final PointerTrackerQueue queue = mPointerTrackerQueue; if (queue != null) { if (isOnModifierKey(x, y)) { // Before processing a down event of modifier key, all pointers already being @@ -333,7 +391,7 @@ public class PointerTracker { } private void onDownEventInternal(int x, int y, long eventTime) { - int keyIndex = mKeyState.onDownKey(x, y, eventTime); + int keyIndex = 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. mIsAllowedSlidingKeyInput = mConfigSlidingKeyInputEnabled || isModifierInternal(keyIndex) @@ -349,7 +407,7 @@ public class PointerTracker { // {@link #setKeyboard}. In those cases, we should update keyIndex according to the new // keyboard layout. if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), false)) - keyIndex = mKeyState.onDownKey(x, y, eventTime); + keyIndex = onDownKey(x, y, eventTime); startRepeatKey(keyIndex); startLongPressTimer(keyIndex); @@ -364,25 +422,23 @@ public class PointerTracker { mIsInSlidingKeyInput = true; } - public void onMoveEvent(int x, int y, long eventTime, PointerTrackerQueue queue) { - if (ENABLE_ASSERTION) checkAssertion(queue); + public void onMoveEvent(int x, int y, long eventTime) { if (DEBUG_MOVE_EVENT) printTouchEvent("onMoveEvent:", x, y, eventTime); if (mKeyAlreadyProcessed) return; - final PointerTrackerKeyState keyState = mKeyState; // TODO: Remove this hacking code if (mIsInSlidingLanguageSwitch) { - ((LatinKeyboard)mKeyboard).updateSpacebarPreviewIcon(x - keyState.getKeyX()); + ((LatinKeyboard)mKeyboard).updateSpacebarPreviewIcon(x - mKeyX); showKeyPreview(mSpaceKeyIndex); return; } - final int lastX = keyState.getLastX(); - final int lastY = keyState.getLastY(); - final int oldKeyIndex = keyState.getKeyIndex(); + final int lastX = mLastX; + final int lastY = mLastY; + final int oldKeyIndex = mKeyIndex; final Key oldKey = getKey(oldKeyIndex); - int keyIndex = keyState.onMoveKey(x, y); + int keyIndex = onMoveKey(x, y); if (isValidKeyIndex(keyIndex)) { if (oldKey == null) { // The pointer has been slid in to the new key, but the finger was not on any keys. @@ -391,8 +447,8 @@ public class PointerTracker { // {@link #setKeyboard}. In those cases, we should update keyIndex according to the // new keyboard layout. if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), true)) - keyIndex = keyState.onMoveKey(x, y); - keyState.onMoveToNewKey(keyIndex, x, y); + keyIndex = onMoveKey(x, y); + onMoveToNewKey(keyIndex, x, y); startLongPressTimer(keyIndex); showKeyPreview(keyIndex); setPressedKeyGraphics(keyIndex); @@ -403,15 +459,15 @@ public class PointerTracker { setReleasedKeyGraphics(oldKeyIndex); callListenerOnRelease(oldKey, oldKey.mCode, true); startSlidingKeyInput(oldKey); - mKeyTimerHandler.cancelKeyTimers(); + mTimerProxy.cancelKeyTimers(); startRepeatKey(keyIndex); if (mIsAllowedSlidingKeyInput) { // This onPress call may have changed keyboard layout. Those cases are detected // at {@link #setKeyboard}. In those cases, we should update keyIndex according // to the new keyboard layout. if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), true)) - keyIndex = keyState.onMoveKey(x, y); - keyState.onMoveToNewKey(keyIndex, x, y); + keyIndex = onMoveKey(x, y); + onMoveToNewKey(keyIndex, x, y); startLongPressTimer(keyIndex); setPressedKeyGraphics(keyIndex); showKeyPreview(keyIndex); @@ -441,7 +497,7 @@ public class PointerTracker { final LatinKeyboard keyboard = ((LatinKeyboard)mKeyboard); if (mSubtypeSwitcher.useSpacebarLanguageSwitcher() && mSubtypeSwitcher.getEnabledKeyboardLocaleCount() > 1) { - final int diff = x - keyState.getKeyX(); + final int diff = x - mKeyX; if (keyboard.shouldTriggerSpacebarSlidingLanguageSwitch(diff)) { // Detect start sliding language switch. mIsInSlidingLanguageSwitch = true; @@ -449,6 +505,7 @@ public class PointerTracker { keyboard.updateSpacebarPreviewIcon(diff); // Display spacebar slide language switcher. showKeyPreview(keyIndex); + final PointerTrackerQueue queue = mPointerTrackerQueue; if (queue != null) queue.releaseAllPointersExcept(this, eventTime, true); } @@ -461,9 +518,9 @@ public class PointerTracker { setReleasedKeyGraphics(oldKeyIndex); callListenerOnRelease(oldKey, oldKey.mCode, true); startSlidingKeyInput(oldKey); - mKeyTimerHandler.cancelLongPressTimers(); + mTimerProxy.cancelLongPressTimers(); if (mIsAllowedSlidingKeyInput) { - keyState.onMoveToNewKey(keyIndex, x, y); + onMoveToNewKey(keyIndex, x, y); } else { mKeyAlreadyProcessed = true; dismissKeyPreview(); @@ -472,11 +529,11 @@ public class PointerTracker { } } - public void onUpEvent(int x, int y, long eventTime, PointerTrackerQueue queue) { - if (ENABLE_ASSERTION) checkAssertion(queue); + public void onUpEvent(int x, int y, long eventTime) { if (DEBUG_EVENT) printTouchEvent("onUpEvent :", x, y, eventTime); + final PointerTrackerQueue queue = mPointerTrackerQueue; if (queue != null) { if (isModifier()) { // Before processing an up event of modifier key, all pointers already being @@ -502,20 +559,19 @@ public class PointerTracker { private void onUpEventInternal(int x, int y, long eventTime, boolean updateReleasedKeyGraphics) { - mKeyTimerHandler.cancelKeyTimers(); + mTimerProxy.cancelKeyTimers(); mDrawingProxy.cancelShowKeyPreview(this); mIsInSlidingKeyInput = false; - final PointerTrackerKeyState keyState = mKeyState; final int keyX, keyY; - if (isMajorEnoughMoveToBeOnNewKey(x, y, keyState.onMoveKey(x, y))) { + if (isMajorEnoughMoveToBeOnNewKey(x, y, onMoveKey(x, y))) { keyX = x; keyY = y; } else { // Use previous fixed key coordinates. - keyX = keyState.getKeyX(); - keyY = keyState.getKeyY(); + keyX = mKeyX; + keyY = mKeyY; } - final int keyIndex = keyState.onUpKey(keyX, keyY, eventTime); + final int keyIndex = onUpKey(keyX, keyY, eventTime); dismissKeyPreview(); if (updateReleasedKeyGraphics) setReleasedKeyGraphics(keyIndex); @@ -540,20 +596,21 @@ public class PointerTracker { } } - public void onLongPressed(PointerTrackerQueue queue) { + public void onLongPressed() { mKeyAlreadyProcessed = true; + setReleasedKeyGraphics(); + dismissKeyPreview(); + final PointerTrackerQueue queue = mPointerTrackerQueue; if (queue != null) { - // TODO: Support chording + long-press input. - queue.releaseAllPointersExcept(this, SystemClock.uptimeMillis(), true); queue.remove(this); } } - public void onCancelEvent(int x, int y, long eventTime, PointerTrackerQueue queue) { - if (ENABLE_ASSERTION) checkAssertion(queue); + public void onCancelEvent(int x, int y, long eventTime) { if (DEBUG_EVENT) printTouchEvent("onCancelEvt:", x, y, eventTime); + final PointerTrackerQueue queue = mPointerTrackerQueue; if (queue != null) { queue.releaseAllPointersExcept(this, eventTime, true); queue.remove(this); @@ -562,10 +619,10 @@ public class PointerTracker { } private void onCancelEventInternal() { - mKeyTimerHandler.cancelKeyTimers(); + mTimerProxy.cancelKeyTimers(); mDrawingProxy.cancelShowKeyPreview(this); dismissKeyPreview(); - setReleasedKeyGraphics(mKeyState.getKeyIndex()); + setReleasedKeyGraphics(mKeyIndex); mIsInSlidingKeyInput = false; } @@ -574,7 +631,7 @@ public class PointerTracker { if (key != null && key.mRepeatable) { dismissKeyPreview(); onRepeatKey(keyIndex); - mKeyTimerHandler.startKeyRepeatTimer(mDelayBeforeKeyRepeatStart, keyIndex, this); + mTimerProxy.startKeyRepeatTimer(mDelayBeforeKeyRepeatStart, keyIndex, this); mIsRepeatableKey = true; } else { mIsRepeatableKey = false; @@ -588,22 +645,10 @@ public class PointerTracker { } } - public int getLastX() { - return mKeyState.getLastX(); - } - - public int getLastY() { - return mKeyState.getLastY(); - } - - public long getDownTime() { - return mKeyState.getDownTime(); - } - private boolean isMajorEnoughMoveToBeOnNewKey(int x, int y, int newKey) { if (mKeys == null || mKeyDetector == null) throw new NullPointerException("keyboard and/or key detector not set"); - int curKey = mKeyState.getKeyIndex(); + int curKey = mKeyIndex; if (newKey == curKey) { return false; } else if (isValidKeyIndex(curKey)) { @@ -640,16 +685,16 @@ public class PointerTracker { private void startLongPressTimer(int keyIndex) { Key key = getKey(keyIndex); if (key.mCode == Keyboard.CODE_SHIFT) { - mKeyTimerHandler.startLongPressShiftTimer(mLongPressShiftKeyTimeout, keyIndex, this); + mTimerProxy.startLongPressShiftTimer(mLongPressShiftKeyTimeout, keyIndex, this); } else if (key.hasUppercaseLetter() && mKeyboard.isManualTemporaryUpperCase()) { // We need not start long press timer on the key which has manual temporary upper case // code defined and the keyboard is in manual temporary upper case mode. return; } else if (mKeyboardSwitcher.isInMomentarySwitchState()) { // We use longer timeout for sliding finger input started from the symbols mode key. - mKeyTimerHandler.startLongPressTimer(mLongPressKeyTimeout * 3, keyIndex, this); + mTimerProxy.startLongPressTimer(mLongPressKeyTimeout * 3, keyIndex, this); } else { - mKeyTimerHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this); + mTimerProxy.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this); } } |