Loading java/src/com/android/inputmethod/latin/KeyboardSwitcher.java +4 −0 Original line number Diff line number Diff line Loading @@ -365,6 +365,10 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha } } public boolean hasDistinctMultitouch() { return mInputView != null && mInputView.hasDistinctMultitouch(); } /** * Updates state machine to figure out when to automatically switch back to alpha mode. * Returns true if the keyboard needs to switch back Loading java/src/com/android/inputmethod/latin/LatinIME.java +6 −4 Original line number Diff line number Diff line Loading @@ -1135,7 +1135,9 @@ public class LatinIME extends InputMethodService LatinImeLogger.logOnDelete(); break; case Keyboard.KEYCODE_SHIFT: // Shift key is handled in onPress(). // Shift key is handled in onPress() when device has distinct multi-touch panel. if (!mKeyboardSwitcher.hasDistinctMultitouch()) handleShift(); break; case Keyboard.KEYCODE_CANCEL: if (!isShowingOptionDialog()) { Loading Loading @@ -1935,7 +1937,7 @@ public class LatinIME extends InputMethodService List<CharSequence> suggestions = mWordToSuggestions.get(selectedWord); // If the first letter of touching is capitalized, make all the suggestions // start with a capital letter. if (Character.isUpperCase((char) touching.word.charAt(0))) { if (Character.isUpperCase(touching.word.charAt(0))) { for (int i = 0; i < suggestions.size(); i++) { String origSugg = (String) suggestions.get(i); String capsSugg = origSugg.toUpperCase().charAt(0) Loading Loading @@ -2196,7 +2198,7 @@ public class LatinIME extends InputMethodService public void onPress(int primaryCode) { vibrate(); playKeyClick(primaryCode); if (primaryCode == Keyboard.KEYCODE_SHIFT) { if (mKeyboardSwitcher.hasDistinctMultitouch() && primaryCode == Keyboard.KEYCODE_SHIFT) { mShiftKeyState.onPress(); handleShift(); } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) { Loading @@ -2210,7 +2212,7 @@ public class LatinIME extends InputMethodService // Reset any drag flags in the keyboard ((LatinKeyboard) mKeyboardSwitcher.getInputView().getKeyboard()).keyReleased(); //vibrate(); if (primaryCode == Keyboard.KEYCODE_SHIFT) { if (mKeyboardSwitcher.hasDistinctMultitouch() && primaryCode == Keyboard.KEYCODE_SHIFT) { if (mShiftKeyState.isMomentary()) resetShift(); mShiftKeyState.onRelease(); Loading java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +50 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.inputmethod.latin; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; Loading Loading @@ -204,6 +205,8 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx private final ArrayList<PointerTracker> mPointerTrackers = new ArrayList<PointerTracker>(); private final PointerQueue mPointerQueue = new PointerQueue(); private final float mDebounceHysteresis; private final boolean mHasDistinctMultitouch; private int mOldPointerCount = 1; protected KeyDetector mKeyDetector = new ProximityKeyDetector(); Loading Loading @@ -508,6 +511,9 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx final boolean ignoreMultitouch = true; mGestureDetector = new GestureDetector(getContext(), listener, null, ignoreMultitouch); mGestureDetector.setIsLongpressEnabled(false); mHasDistinctMultitouch = context.getPackageManager() .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT); } public void setOnKeyboardActionListener(OnKeyboardActionListener listener) { Loading Loading @@ -563,6 +569,14 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx return mKeyboard; } /** * Return whether the device has distinct multi-touch panel. * @return true if the device has distinct multi-touch panel. */ public boolean hasDistinctMultitouch() { return mHasDistinctMultitouch; } /** * Sets the state of the shift key of the keyboard, if any. * @param shifted whether or not to enable the state of the shift key Loading Loading @@ -1090,7 +1104,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx // Create pointer trackers until we can get 'id+1'-th tracker, if needed. for (int i = pointers.size(); i <= id; i++) { final PointerTracker tracker = new PointerTracker(i, mHandler, mKeyDetector, this); new PointerTracker(i, mHandler, mKeyDetector, this, mHasDistinctMultitouch); if (keys != null) tracker.setKeyboard(keys, mDebounceHysteresis); if (listener != null) Loading @@ -1107,6 +1121,13 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx final int action = me.getActionMasked(); final long eventTime = me.getEventTime(); // TODO: cleanup this code into a multi-touch to single-touch event converter class? // If the device does not have distinct multi-touch support panel, ignore all multi-touch // events except a transition from/to single-touch. if (!mHasDistinctMultitouch && pointerCount > 1 && mOldPointerCount > 1) { return true; } // Track the last few movements to look for spurious swipes. mSwipeTracker.addMovement(me); Loading Loading @@ -1138,6 +1159,34 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx // Up event will pass through. } // TODO: cleanup this code into a multi-touch to single-touch event converter class? // Translate mutli-touch event to single-touch events on the device that has no distinct // multi-touch panel. if (!mHasDistinctMultitouch) { // Use only main (id=0) pointer tracker. PointerTracker tracker = getPointerTracker(0); int index = me.getActionIndex(); int x = (int)me.getX(index); int y = (int)me.getY(index); int oldPointerCount = mOldPointerCount; if (pointerCount == 1 && oldPointerCount == 2) { // Multi-touch to single touch transition. // Send a down event for the latest pointer. tracker.onDownEvent(x, y, eventTime); } else if (pointerCount == 2 && oldPointerCount == 1) { // Single-touch to multi-touch transition. // Send an up event for the last pointer. tracker.onUpEvent(tracker.getLastX(), tracker.getLastY(), eventTime); } else if (pointerCount == 1 && oldPointerCount == 1) { tracker.onTouchEvent(action, x, y, eventTime); } else { Log.w(TAG, "Unknown touch panel behavior: pointer count is " + pointerCount + " (old " + oldPointerCount + ")"); } mOldPointerCount = pointerCount; return true; } if (action == MotionEvent.ACTION_MOVE) { for (int index = 0; index < pointerCount; index++) { int x = (int)me.getX(index); Loading java/src/com/android/inputmethod/latin/PointerTracker.java +30 −4 Original line number Diff line number Diff line Loading @@ -22,12 +22,13 @@ import com.android.inputmethod.latin.LatinKeyboardBaseView.UIHandler; import android.inputmethodservice.Keyboard; import android.inputmethodservice.Keyboard.Key; import android.util.Log; import android.view.MotionEvent; import android.view.ViewConfiguration; public class PointerTracker { private static final String TAG = "PointerTracker"; private static final boolean DEBUG = false; private static final boolean DEBUG_MOVE = DEBUG && true; private static final boolean DEBUG_MOVE = false; public interface UIProxy { public void invalidateKey(Key key); Loading @@ -51,6 +52,7 @@ public class PointerTracker { private final UIHandler mHandler; private final KeyDetector mKeyDetector; private OnKeyboardActionListener mListener; private final boolean mHasDistinctMultitouch; private Key[] mKeys; private int mKeyDebounceThresholdSquared = -1; Loading Loading @@ -85,13 +87,15 @@ public class PointerTracker { // pressed key private int mPreviousKey = NOT_A_KEY; public PointerTracker(int id, UIHandler handler, KeyDetector keyDetector, UIProxy proxy) { public PointerTracker(int id, UIHandler handler, KeyDetector keyDetector, UIProxy proxy, boolean hasDistinctMultitouch) { if (proxy == null || handler == null || keyDetector == null) throw new NullPointerException(); mPointerId = id; mProxy = proxy; mHandler = handler; mKeyDetector = keyDetector; mHasDistinctMultitouch = hasDistinctMultitouch; resetMultiTap(); } Loading Loading @@ -146,6 +150,25 @@ public class PointerTracker { mKeyAlreadyProcessed = true; } public void onTouchEvent(int action, int x, int y, long eventTime) { switch (action) { case MotionEvent.ACTION_MOVE: onMoveEvent(x, y, eventTime); break; case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_POINTER_DOWN: onDownEvent(x, y, eventTime); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: onUpEvent(x, y, eventTime); break; case MotionEvent.ACTION_CANCEL: onCancelEvent(x, y, eventTime); break; } } public void onDownEvent(int x, int y, long eventTime) { int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null); mCurrentKey = keyIndex; Loading Loading @@ -242,7 +265,7 @@ public class PointerTracker { showKeyPreviewAndUpdateKey(NOT_A_KEY); // If we're not on a repeating key (which sends on a DOWN event) if (!wasInKeyRepeat) { detectAndSendKey(mCurrentKey, (int)x, (int)y, eventTime); detectAndSendKey(mCurrentKey, x, y, eventTime); } if (isValidKeyIndex(keyIndex)) mProxy.invalidateKey(mKeys[keyIndex]); Loading Loading @@ -355,7 +378,10 @@ public class PointerTracker { private void showKeyPreviewAndUpdateKey(int keyIndex) { updateKey(keyIndex); if (!isModifier()) // The modifier key, such as shift key, should not be shown as preview when multi-touch is // supported. On thge other hand, if multi-touch is not supported, the modifier key should // be shown as preview. if (!isModifier() || !mHasDistinctMultitouch) mProxy.showPreview(keyIndex, this); } Loading Loading
java/src/com/android/inputmethod/latin/KeyboardSwitcher.java +4 −0 Original line number Diff line number Diff line Loading @@ -365,6 +365,10 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha } } public boolean hasDistinctMultitouch() { return mInputView != null && mInputView.hasDistinctMultitouch(); } /** * Updates state machine to figure out when to automatically switch back to alpha mode. * Returns true if the keyboard needs to switch back Loading
java/src/com/android/inputmethod/latin/LatinIME.java +6 −4 Original line number Diff line number Diff line Loading @@ -1135,7 +1135,9 @@ public class LatinIME extends InputMethodService LatinImeLogger.logOnDelete(); break; case Keyboard.KEYCODE_SHIFT: // Shift key is handled in onPress(). // Shift key is handled in onPress() when device has distinct multi-touch panel. if (!mKeyboardSwitcher.hasDistinctMultitouch()) handleShift(); break; case Keyboard.KEYCODE_CANCEL: if (!isShowingOptionDialog()) { Loading Loading @@ -1935,7 +1937,7 @@ public class LatinIME extends InputMethodService List<CharSequence> suggestions = mWordToSuggestions.get(selectedWord); // If the first letter of touching is capitalized, make all the suggestions // start with a capital letter. if (Character.isUpperCase((char) touching.word.charAt(0))) { if (Character.isUpperCase(touching.word.charAt(0))) { for (int i = 0; i < suggestions.size(); i++) { String origSugg = (String) suggestions.get(i); String capsSugg = origSugg.toUpperCase().charAt(0) Loading Loading @@ -2196,7 +2198,7 @@ public class LatinIME extends InputMethodService public void onPress(int primaryCode) { vibrate(); playKeyClick(primaryCode); if (primaryCode == Keyboard.KEYCODE_SHIFT) { if (mKeyboardSwitcher.hasDistinctMultitouch() && primaryCode == Keyboard.KEYCODE_SHIFT) { mShiftKeyState.onPress(); handleShift(); } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) { Loading @@ -2210,7 +2212,7 @@ public class LatinIME extends InputMethodService // Reset any drag flags in the keyboard ((LatinKeyboard) mKeyboardSwitcher.getInputView().getKeyboard()).keyReleased(); //vibrate(); if (primaryCode == Keyboard.KEYCODE_SHIFT) { if (mKeyboardSwitcher.hasDistinctMultitouch() && primaryCode == Keyboard.KEYCODE_SHIFT) { if (mShiftKeyState.isMomentary()) resetShift(); mShiftKeyState.onRelease(); Loading
java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +50 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.inputmethod.latin; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; Loading Loading @@ -204,6 +205,8 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx private final ArrayList<PointerTracker> mPointerTrackers = new ArrayList<PointerTracker>(); private final PointerQueue mPointerQueue = new PointerQueue(); private final float mDebounceHysteresis; private final boolean mHasDistinctMultitouch; private int mOldPointerCount = 1; protected KeyDetector mKeyDetector = new ProximityKeyDetector(); Loading Loading @@ -508,6 +511,9 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx final boolean ignoreMultitouch = true; mGestureDetector = new GestureDetector(getContext(), listener, null, ignoreMultitouch); mGestureDetector.setIsLongpressEnabled(false); mHasDistinctMultitouch = context.getPackageManager() .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT); } public void setOnKeyboardActionListener(OnKeyboardActionListener listener) { Loading Loading @@ -563,6 +569,14 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx return mKeyboard; } /** * Return whether the device has distinct multi-touch panel. * @return true if the device has distinct multi-touch panel. */ public boolean hasDistinctMultitouch() { return mHasDistinctMultitouch; } /** * Sets the state of the shift key of the keyboard, if any. * @param shifted whether or not to enable the state of the shift key Loading Loading @@ -1090,7 +1104,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx // Create pointer trackers until we can get 'id+1'-th tracker, if needed. for (int i = pointers.size(); i <= id; i++) { final PointerTracker tracker = new PointerTracker(i, mHandler, mKeyDetector, this); new PointerTracker(i, mHandler, mKeyDetector, this, mHasDistinctMultitouch); if (keys != null) tracker.setKeyboard(keys, mDebounceHysteresis); if (listener != null) Loading @@ -1107,6 +1121,13 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx final int action = me.getActionMasked(); final long eventTime = me.getEventTime(); // TODO: cleanup this code into a multi-touch to single-touch event converter class? // If the device does not have distinct multi-touch support panel, ignore all multi-touch // events except a transition from/to single-touch. if (!mHasDistinctMultitouch && pointerCount > 1 && mOldPointerCount > 1) { return true; } // Track the last few movements to look for spurious swipes. mSwipeTracker.addMovement(me); Loading Loading @@ -1138,6 +1159,34 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx // Up event will pass through. } // TODO: cleanup this code into a multi-touch to single-touch event converter class? // Translate mutli-touch event to single-touch events on the device that has no distinct // multi-touch panel. if (!mHasDistinctMultitouch) { // Use only main (id=0) pointer tracker. PointerTracker tracker = getPointerTracker(0); int index = me.getActionIndex(); int x = (int)me.getX(index); int y = (int)me.getY(index); int oldPointerCount = mOldPointerCount; if (pointerCount == 1 && oldPointerCount == 2) { // Multi-touch to single touch transition. // Send a down event for the latest pointer. tracker.onDownEvent(x, y, eventTime); } else if (pointerCount == 2 && oldPointerCount == 1) { // Single-touch to multi-touch transition. // Send an up event for the last pointer. tracker.onUpEvent(tracker.getLastX(), tracker.getLastY(), eventTime); } else if (pointerCount == 1 && oldPointerCount == 1) { tracker.onTouchEvent(action, x, y, eventTime); } else { Log.w(TAG, "Unknown touch panel behavior: pointer count is " + pointerCount + " (old " + oldPointerCount + ")"); } mOldPointerCount = pointerCount; return true; } if (action == MotionEvent.ACTION_MOVE) { for (int index = 0; index < pointerCount; index++) { int x = (int)me.getX(index); Loading
java/src/com/android/inputmethod/latin/PointerTracker.java +30 −4 Original line number Diff line number Diff line Loading @@ -22,12 +22,13 @@ import com.android.inputmethod.latin.LatinKeyboardBaseView.UIHandler; import android.inputmethodservice.Keyboard; import android.inputmethodservice.Keyboard.Key; import android.util.Log; import android.view.MotionEvent; import android.view.ViewConfiguration; public class PointerTracker { private static final String TAG = "PointerTracker"; private static final boolean DEBUG = false; private static final boolean DEBUG_MOVE = DEBUG && true; private static final boolean DEBUG_MOVE = false; public interface UIProxy { public void invalidateKey(Key key); Loading @@ -51,6 +52,7 @@ public class PointerTracker { private final UIHandler mHandler; private final KeyDetector mKeyDetector; private OnKeyboardActionListener mListener; private final boolean mHasDistinctMultitouch; private Key[] mKeys; private int mKeyDebounceThresholdSquared = -1; Loading Loading @@ -85,13 +87,15 @@ public class PointerTracker { // pressed key private int mPreviousKey = NOT_A_KEY; public PointerTracker(int id, UIHandler handler, KeyDetector keyDetector, UIProxy proxy) { public PointerTracker(int id, UIHandler handler, KeyDetector keyDetector, UIProxy proxy, boolean hasDistinctMultitouch) { if (proxy == null || handler == null || keyDetector == null) throw new NullPointerException(); mPointerId = id; mProxy = proxy; mHandler = handler; mKeyDetector = keyDetector; mHasDistinctMultitouch = hasDistinctMultitouch; resetMultiTap(); } Loading Loading @@ -146,6 +150,25 @@ public class PointerTracker { mKeyAlreadyProcessed = true; } public void onTouchEvent(int action, int x, int y, long eventTime) { switch (action) { case MotionEvent.ACTION_MOVE: onMoveEvent(x, y, eventTime); break; case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_POINTER_DOWN: onDownEvent(x, y, eventTime); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: onUpEvent(x, y, eventTime); break; case MotionEvent.ACTION_CANCEL: onCancelEvent(x, y, eventTime); break; } } public void onDownEvent(int x, int y, long eventTime) { int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null); mCurrentKey = keyIndex; Loading Loading @@ -242,7 +265,7 @@ public class PointerTracker { showKeyPreviewAndUpdateKey(NOT_A_KEY); // If we're not on a repeating key (which sends on a DOWN event) if (!wasInKeyRepeat) { detectAndSendKey(mCurrentKey, (int)x, (int)y, eventTime); detectAndSendKey(mCurrentKey, x, y, eventTime); } if (isValidKeyIndex(keyIndex)) mProxy.invalidateKey(mKeys[keyIndex]); Loading Loading @@ -355,7 +378,10 @@ public class PointerTracker { private void showKeyPreviewAndUpdateKey(int keyIndex) { updateKey(keyIndex); if (!isModifier()) // The modifier key, such as shift key, should not be shown as preview when multi-touch is // supported. On thge other hand, if multi-touch is not supported, the modifier key should // be shown as preview. if (!isModifier() || !mHasDistinctMultitouch) mProxy.showPreview(keyIndex, this); } Loading