am d5bcbf81: am c8b9afe0: Support multi-touch only when device has distinct multi-touch panel

Merge commit 'd5bcbf8156fdba8199452b8f95ed1940b7e96d31'

* commit 'd5bcbf8156fdba8199452b8f95ed1940b7e96d31':
  Support multi-touch only when device has distinct multi-touch panel
This commit is contained in:
Tadashi G. Takaoka 2010-09-06 02:19:13 -07:00 committed by Android Git Automerger
commit cba7b0b6ab
4 changed files with 90 additions and 9 deletions

View file

@ -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. * Updates state machine to figure out when to automatically switch back to alpha mode.
* Returns true if the keyboard needs to switch back * Returns true if the keyboard needs to switch back

View file

@ -1134,7 +1134,9 @@ public class LatinIME extends InputMethodService
LatinImeLogger.logOnDelete(); LatinImeLogger.logOnDelete();
break; break;
case Keyboard.KEYCODE_SHIFT: 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; break;
case Keyboard.KEYCODE_CANCEL: case Keyboard.KEYCODE_CANCEL:
if (!isShowingOptionDialog()) { if (!isShowingOptionDialog()) {
@ -1934,7 +1936,7 @@ public class LatinIME extends InputMethodService
List<CharSequence> suggestions = mWordToSuggestions.get(selectedWord); List<CharSequence> suggestions = mWordToSuggestions.get(selectedWord);
// If the first letter of touching is capitalized, make all the suggestions // If the first letter of touching is capitalized, make all the suggestions
// start with a capital letter. // 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++) { for (int i = 0; i < suggestions.size(); i++) {
String origSugg = (String) suggestions.get(i); String origSugg = (String) suggestions.get(i);
String capsSugg = origSugg.toUpperCase().charAt(0) String capsSugg = origSugg.toUpperCase().charAt(0)
@ -2195,7 +2197,7 @@ public class LatinIME extends InputMethodService
public void onPress(int primaryCode) { public void onPress(int primaryCode) {
vibrate(); vibrate();
playKeyClick(primaryCode); playKeyClick(primaryCode);
if (primaryCode == Keyboard.KEYCODE_SHIFT) { if (mKeyboardSwitcher.hasDistinctMultitouch() && primaryCode == Keyboard.KEYCODE_SHIFT) {
mShiftKeyState.onPress(); mShiftKeyState.onPress();
handleShift(); handleShift();
} else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) { } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
@ -2209,7 +2211,7 @@ public class LatinIME extends InputMethodService
// Reset any drag flags in the keyboard // Reset any drag flags in the keyboard
((LatinKeyboard) mKeyboardSwitcher.getInputView().getKeyboard()).keyReleased(); ((LatinKeyboard) mKeyboardSwitcher.getInputView().getKeyboard()).keyReleased();
//vibrate(); //vibrate();
if (primaryCode == Keyboard.KEYCODE_SHIFT) { if (mKeyboardSwitcher.hasDistinctMultitouch() && primaryCode == Keyboard.KEYCODE_SHIFT) {
if (mShiftKeyState.isMomentary()) if (mShiftKeyState.isMomentary())
resetShift(); resetShift();
mShiftKeyState.onRelease(); mShiftKeyState.onRelease();

View file

@ -17,6 +17,7 @@
package com.android.inputmethod.latin; package com.android.inputmethod.latin;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -204,6 +205,8 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
private final ArrayList<PointerTracker> mPointerTrackers = new ArrayList<PointerTracker>(); private final ArrayList<PointerTracker> mPointerTrackers = new ArrayList<PointerTracker>();
private final PointerQueue mPointerQueue = new PointerQueue(); private final PointerQueue mPointerQueue = new PointerQueue();
private final float mDebounceHysteresis; private final float mDebounceHysteresis;
private final boolean mHasDistinctMultitouch;
private int mOldPointerCount = 1;
protected KeyDetector mKeyDetector = new ProximityKeyDetector(); protected KeyDetector mKeyDetector = new ProximityKeyDetector();
@ -508,6 +511,9 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
final boolean ignoreMultitouch = true; final boolean ignoreMultitouch = true;
mGestureDetector = new GestureDetector(getContext(), listener, null, ignoreMultitouch); mGestureDetector = new GestureDetector(getContext(), listener, null, ignoreMultitouch);
mGestureDetector.setIsLongpressEnabled(false); mGestureDetector.setIsLongpressEnabled(false);
mHasDistinctMultitouch = context.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT);
} }
public void setOnKeyboardActionListener(OnKeyboardActionListener listener) { public void setOnKeyboardActionListener(OnKeyboardActionListener listener) {
@ -563,6 +569,14 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
return mKeyboard; 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. * 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 * @param shifted whether or not to enable the state of the shift key
@ -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. // Create pointer trackers until we can get 'id+1'-th tracker, if needed.
for (int i = pointers.size(); i <= id; i++) { for (int i = pointers.size(); i <= id; i++) {
final PointerTracker tracker = final PointerTracker tracker =
new PointerTracker(i, mHandler, mKeyDetector, this); new PointerTracker(i, mHandler, mKeyDetector, this, mHasDistinctMultitouch);
if (keys != null) if (keys != null)
tracker.setKeyboard(keys, mDebounceHysteresis); tracker.setKeyboard(keys, mDebounceHysteresis);
if (listener != null) if (listener != null)
@ -1107,6 +1121,13 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
final int action = me.getActionMasked(); final int action = me.getActionMasked();
final long eventTime = me.getEventTime(); 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. // Track the last few movements to look for spurious swipes.
mSwipeTracker.addMovement(me); mSwipeTracker.addMovement(me);
@ -1138,6 +1159,34 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
// Up event will pass through. // 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) { if (action == MotionEvent.ACTION_MOVE) {
for (int index = 0; index < pointerCount; index++) { for (int index = 0; index < pointerCount; index++) {
int x = (int)me.getX(index); int x = (int)me.getX(index);

View file

@ -22,12 +22,13 @@ import com.android.inputmethod.latin.LatinKeyboardBaseView.UIHandler;
import android.inputmethodservice.Keyboard; import android.inputmethodservice.Keyboard;
import android.inputmethodservice.Keyboard.Key; import android.inputmethodservice.Keyboard.Key;
import android.util.Log; import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewConfiguration; import android.view.ViewConfiguration;
public class PointerTracker { public class PointerTracker {
private static final String TAG = "PointerTracker"; private static final String TAG = "PointerTracker";
private static final boolean DEBUG = false; 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 interface UIProxy {
public void invalidateKey(Key key); public void invalidateKey(Key key);
@ -51,6 +52,7 @@ public class PointerTracker {
private final UIHandler mHandler; private final UIHandler mHandler;
private final KeyDetector mKeyDetector; private final KeyDetector mKeyDetector;
private OnKeyboardActionListener mListener; private OnKeyboardActionListener mListener;
private final boolean mHasDistinctMultitouch;
private Key[] mKeys; private Key[] mKeys;
private int mKeyDebounceThresholdSquared = -1; private int mKeyDebounceThresholdSquared = -1;
@ -85,13 +87,15 @@ public class PointerTracker {
// pressed key // pressed key
private int mPreviousKey = NOT_A_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) if (proxy == null || handler == null || keyDetector == null)
throw new NullPointerException(); throw new NullPointerException();
mPointerId = id; mPointerId = id;
mProxy = proxy; mProxy = proxy;
mHandler = handler; mHandler = handler;
mKeyDetector = keyDetector; mKeyDetector = keyDetector;
mHasDistinctMultitouch = hasDistinctMultitouch;
resetMultiTap(); resetMultiTap();
} }
@ -146,6 +150,25 @@ public class PointerTracker {
mKeyAlreadyProcessed = true; 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) { public void onDownEvent(int x, int y, long eventTime) {
int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null); int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null);
mCurrentKey = keyIndex; mCurrentKey = keyIndex;
@ -242,7 +265,7 @@ public class PointerTracker {
showKeyPreviewAndUpdateKey(NOT_A_KEY); showKeyPreviewAndUpdateKey(NOT_A_KEY);
// If we're not on a repeating key (which sends on a DOWN event) // If we're not on a repeating key (which sends on a DOWN event)
if (!wasInKeyRepeat) { if (!wasInKeyRepeat) {
detectAndSendKey(mCurrentKey, (int)x, (int)y, eventTime); detectAndSendKey(mCurrentKey, x, y, eventTime);
} }
if (isValidKeyIndex(keyIndex)) if (isValidKeyIndex(keyIndex))
mProxy.invalidateKey(mKeys[keyIndex]); mProxy.invalidateKey(mKeys[keyIndex]);
@ -355,7 +378,10 @@ public class PointerTracker {
private void showKeyPreviewAndUpdateKey(int keyIndex) { private void showKeyPreviewAndUpdateKey(int keyIndex) {
updateKey(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); mProxy.showPreview(keyIndex, this);
} }