Add separate key hysteresis distance for sliding modifier input

Bug: 7294402
Change-Id: I78c8be9e1a7b2d49d86bfe1e3a46d1785bfe5d48
main
Tadashi G. Takaoka 2012-10-06 23:22:36 +09:00
parent 448e732272
commit f731eb1760
6 changed files with 48 additions and 22 deletions

View File

@ -109,6 +109,8 @@
<attr name="altCodeKeyWhileTypingFadeinAnimator" format="reference" /> <attr name="altCodeKeyWhileTypingFadeinAnimator" format="reference" />
<!-- Key detection hysteresis distance. --> <!-- Key detection hysteresis distance. -->
<attr name="keyHysteresisDistance" format="dimension" /> <attr name="keyHysteresisDistance" format="dimension" />
<!-- Key detection hysteresis distance for shift/symbols sliding input. -->
<attr name="keyHysteresisDistanceForSlidingModifier" format="dimension" />
<!-- Touch noise threshold time in millisecond --> <!-- Touch noise threshold time in millisecond -->
<attr name="touchNoiseThresholdTime" format="integer" /> <attr name="touchNoiseThresholdTime" format="integer" />
<!-- Touch noise threshold distance in millimeter --> <!-- Touch noise threshold distance in millimeter -->

View File

@ -57,6 +57,7 @@
Configuration for MainKeyboardView Configuration for MainKeyboardView
--> -->
<dimen name="config_key_hysteresis_distance">8.0dp</dimen> <dimen name="config_key_hysteresis_distance">8.0dp</dimen>
<dimen name="config_key_hysteresis_distance_for_sliding_modifier">8.0dp</dimen>
<integer name="config_touch_noise_threshold_time">40</integer> <integer name="config_touch_noise_threshold_time">40</integer>
<dimen name="config_touch_noise_threshold_distance">12.6dp</dimen> <dimen name="config_touch_noise_threshold_distance">12.6dp</dimen>
<bool name="config_sliding_key_input_enabled">true</bool> <bool name="config_sliding_key_input_enabled">true</bool>

View File

@ -81,6 +81,7 @@
<item name="gesturePreviewTrailEndWidth">@dimen/gesture_preview_trail_end_width</item> <item name="gesturePreviewTrailEndWidth">@dimen/gesture_preview_trail_end_width</item>
<!-- Common attributes of MainKeyboardView --> <!-- Common attributes of MainKeyboardView -->
<item name="keyHysteresisDistance">@dimen/config_key_hysteresis_distance</item> <item name="keyHysteresisDistance">@dimen/config_key_hysteresis_distance</item>
<item name="keyHysteresisDistanceForSlidingModifier">@dimen/config_key_hysteresis_distance_for_sliding_modifier</item>
<item name="touchNoiseThresholdTime">@integer/config_touch_noise_threshold_time</item> <item name="touchNoiseThresholdTime">@integer/config_touch_noise_threshold_time</item>
<item name="touchNoiseThresholdDistance">@dimen/config_touch_noise_threshold_distance</item> <item name="touchNoiseThresholdDistance">@dimen/config_touch_noise_threshold_distance</item>
<item name="slidingKeyInputEnable">@bool/config_sliding_key_input_enabled</item> <item name="slidingKeyInputEnable">@bool/config_sliding_key_input_enabled</item>

View File

@ -21,6 +21,7 @@ import com.android.inputmethod.latin.Constants;
public class KeyDetector { public class KeyDetector {
private final int mKeyHysteresisDistanceSquared; private final int mKeyHysteresisDistanceSquared;
private final int mKeyHysteresisDistanceForSlidingModifierSquared;
private Keyboard mKeyboard; private Keyboard mKeyboard;
private int mCorrectionX; private int mCorrectionX;
@ -30,10 +31,24 @@ public class KeyDetector {
* This class handles key detection. * This class handles key detection.
* *
* @param keyHysteresisDistance if the pointer movement distance is smaller than this, the * @param keyHysteresisDistance if the pointer movement distance is smaller than this, the
* movement will not been handled as meaningful movement. The unit is pixel. * movement will not be handled as meaningful movement. The unit is pixel.
*/ */
public KeyDetector(float keyHysteresisDistance) { public KeyDetector(float keyHysteresisDistance) {
this(keyHysteresisDistance, keyHysteresisDistance);
}
/**
* This class handles key detection.
*
* @param keyHysteresisDistance if the pointer movement distance is smaller than this, the
* movement will not be handled as meaningful movement. The unit is pixel.
* @param keyHysteresisDistanceForSlidingModifier the same parameter for sliding input that
* starts from a modifier key such as shift and symbols key.
*/
public KeyDetector(float keyHysteresisDistance, float keyHysteresisDistanceForSlidingModifier) {
mKeyHysteresisDistanceSquared = (int)(keyHysteresisDistance * keyHysteresisDistance); mKeyHysteresisDistanceSquared = (int)(keyHysteresisDistance * keyHysteresisDistance);
mKeyHysteresisDistanceForSlidingModifierSquared = (int)(
keyHysteresisDistanceForSlidingModifier * keyHysteresisDistanceForSlidingModifier);
} }
public void setKeyboard(Keyboard keyboard, float correctionX, float correctionY) { public void setKeyboard(Keyboard keyboard, float correctionX, float correctionY) {
@ -45,8 +60,9 @@ public class KeyDetector {
mKeyboard = keyboard; mKeyboard = keyboard;
} }
public int getKeyHysteresisDistanceSquared() { public int getKeyHysteresisDistanceSquared(boolean isSlidingFromModifier) {
return mKeyHysteresisDistanceSquared; return isSlidingFromModifier
? mKeyHysteresisDistanceForSlidingModifierSquared : mKeyHysteresisDistanceSquared;
} }
public int getTouchX(int x) { public int getTouchX(int x) {

View File

@ -389,7 +389,10 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
final float keyHysteresisDistance = a.getDimension( final float keyHysteresisDistance = a.getDimension(
R.styleable.MainKeyboardView_keyHysteresisDistance, 0); R.styleable.MainKeyboardView_keyHysteresisDistance, 0);
mKeyDetector = new KeyDetector(keyHysteresisDistance); final float keyHysteresisDistanceForSlidingModifier = a.getDimension(
R.styleable.MainKeyboardView_keyHysteresisDistanceForSlidingModifier, 0);
mKeyDetector = new KeyDetector(
keyHysteresisDistance, keyHysteresisDistanceForSlidingModifier);
mKeyTimerHandler = new KeyTimerHandler(this, a); mKeyTimerHandler = new KeyTimerHandler(this, a);
mConfigShowMoreKeysKeyboardAtTouchedPoint = a.getBoolean( mConfigShowMoreKeysKeyboardAtTouchedPoint = a.getBoolean(
R.styleable.MainKeyboardView_showMoreKeysKeyboardAtTouchedPoint, false); R.styleable.MainKeyboardView_showMoreKeysKeyboardAtTouchedPoint, false);

View File

@ -268,15 +268,15 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
// true if this pointer has been long-pressed and is showing a more keys panel. // true if this pointer has been long-pressed and is showing a more keys panel.
private boolean mIsShowingMoreKeysPanel; private boolean mIsShowingMoreKeysPanel;
// true if this pointer is in sliding key input // true if this pointer is in a sliding key input.
boolean mIsInSlidingKeyInput; boolean mIsInSlidingKeyInput;
// true if this pointer is in a sliding key input from a modifier key,
// so that further modifier keys should be ignored.
boolean mIsInSlidingKeyInputFromModifier;
// true if sliding key is allowed. // true if a sliding key input is allowed.
private boolean mIsAllowedSlidingKeyInput; private boolean mIsAllowedSlidingKeyInput;
// ignore modifier key if true
private boolean mIgnoreModifierKey;
// Empty {@link KeyboardActionListener} // Empty {@link KeyboardActionListener}
private static final KeyboardActionListener EMPTY_LISTENER = private static final KeyboardActionListener EMPTY_LISTENER =
new KeyboardActionListener.Adapter(); new KeyboardActionListener.Adapter();
@ -383,7 +383,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
if (sInGesture) { if (sInGesture) {
return false; return false;
} }
final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier(); final boolean ignoreModifierKey = mIsInSlidingKeyInputFromModifier && key.isModifier();
if (DEBUG_LISTENER) { if (DEBUG_LISTENER) {
Log.d(TAG, String.format("[%d] onPress : %s%s%s", mPointerId, Log.d(TAG, String.format("[%d] onPress : %s%s%s", mPointerId,
KeyDetector.printableCode(key), KeyDetector.printableCode(key),
@ -407,7 +407,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
// primaryCode is different from {@link Key#mCode}. // primaryCode is different from {@link Key#mCode}.
private void callListenerOnCodeInput(final Key key, final int primaryCode, final int x, private void callListenerOnCodeInput(final Key key, final int primaryCode, final int x,
final int y, final long eventTime) { final int y, final long eventTime) {
final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier(); final boolean ignoreModifierKey = mIsInSlidingKeyInputFromModifier && key.isModifier();
final boolean altersCode = key.altCodeWhileTyping() && mTimerProxy.isTypingState(); final boolean altersCode = key.altCodeWhileTyping() && mTimerProxy.isTypingState();
final int code = altersCode ? key.getAltCode() : primaryCode; final int code = altersCode ? key.getAltCode() : primaryCode;
if (DEBUG_LISTENER) { if (DEBUG_LISTENER) {
@ -435,14 +435,14 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
} }
} }
// Note that we need primaryCode argument because the keyboard may in shifted state and the // Note that we need primaryCode argument because the keyboard may be in shifted state and the
// primaryCode is different from {@link Key#mCode}. // primaryCode is different from {@link Key#mCode}.
private void callListenerOnRelease(final Key key, final int primaryCode, private void callListenerOnRelease(final Key key, final int primaryCode,
final boolean withSliding) { final boolean withSliding) {
if (sInGesture) { if (sInGesture) {
return; return;
} }
final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier(); final boolean ignoreModifierKey = mIsInSlidingKeyInputFromModifier && key.isModifier();
if (DEBUG_LISTENER) { if (DEBUG_LISTENER) {
Log.d(TAG, String.format("[%d] onRelease : %s%s%s%s", mPointerId, Log.d(TAG, String.format("[%d] onRelease : %s%s%s%s", mPointerId,
Keyboard.printableCode(primaryCode), Keyboard.printableCode(primaryCode),
@ -778,8 +778,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|| mKeyDetector.alwaysAllowsSlidingInput(); || mKeyDetector.alwaysAllowsSlidingInput();
mKeyboardLayoutHasBeenChanged = false; mKeyboardLayoutHasBeenChanged = false;
mKeyAlreadyProcessed = false; mKeyAlreadyProcessed = false;
mIsInSlidingKeyInput = false; resetSlidingKeyInput();
mIgnoreModifierKey = false;
if (key != null) { if (key != null) {
// This onPress call may have changed keyboard layout. Those cases are detected at // 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 // {@link #setKeyboard}. In those cases, we should update key according to the new
@ -796,11 +795,16 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
private void startSlidingKeyInput(final Key key) { private void startSlidingKeyInput(final Key key) {
if (!mIsInSlidingKeyInput) { if (!mIsInSlidingKeyInput) {
mIgnoreModifierKey = key.isModifier(); mIsInSlidingKeyInputFromModifier = key.isModifier();
} }
mIsInSlidingKeyInput = true; mIsInSlidingKeyInput = true;
} }
private void resetSlidingKeyInput() {
mIsInSlidingKeyInput = false;
mIsInSlidingKeyInputFromModifier = false;
}
private void onGestureMoveEvent(final int x, final int y, final long eventTime, private void onGestureMoveEvent(final int x, final int y, final long eventTime,
final boolean isMajorEvent, final Key key) { final boolean isMajorEvent, final Key key) {
final int gestureTime = (int)(eventTime - sGestureFirstDownTime); final int gestureTime = (int)(eventTime - sGestureFirstDownTime);
@ -847,9 +851,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
// Register move event on gesture tracker. // Register move event on gesture tracker.
onGestureMoveEvent(x, y, eventTime, true /* isMajorEvent */, key); onGestureMoveEvent(x, y, eventTime, true /* isMajorEvent */, key);
if (sInGesture) { if (sInGesture) {
mIgnoreModifierKey = true;
mTimerProxy.cancelLongPressTimer(); mTimerProxy.cancelLongPressTimer();
mIsInSlidingKeyInput = true;
mCurrentKey = null; mCurrentKey = null;
setReleasedKeyGraphics(oldKey); setReleasedKeyGraphics(oldKey);
return; return;
@ -983,7 +985,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
private void onUpEventInternal(final long eventTime) { private void onUpEventInternal(final long eventTime) {
mTimerProxy.cancelKeyTimers(); mTimerProxy.cancelKeyTimers();
mIsInSlidingKeyInput = false; resetSlidingKeyInput();
mIsDetectingGesture = false; mIsDetectingGesture = false;
final Key currentKey = mCurrentKey; final Key currentKey = mCurrentKey;
mCurrentKey = null; mCurrentKey = null;
@ -1041,7 +1043,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
private void onCancelEventInternal() { private void onCancelEventInternal() {
mTimerProxy.cancelKeyTimers(); mTimerProxy.cancelKeyTimers();
setReleasedKeyGraphics(mCurrentKey); setReleasedKeyGraphics(mCurrentKey);
mIsInSlidingKeyInput = false; resetSlidingKeyInput();
if (mIsShowingMoreKeysPanel) { if (mIsShowingMoreKeysPanel) {
mDrawingProxy.dismissMoreKeysPanel(); mDrawingProxy.dismissMoreKeysPanel();
mIsShowingMoreKeysPanel = false; mIsShowingMoreKeysPanel = false;
@ -1070,8 +1072,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
if (newKey == curKey) { if (newKey == curKey) {
return false; return false;
} else if (curKey != null) { } else if (curKey != null) {
return curKey.squaredDistanceToEdge(x, y) final int keyHysteresisDistanceSquared = mKeyDetector.getKeyHysteresisDistanceSquared(
>= mKeyDetector.getKeyHysteresisDistanceSquared(); mIsInSlidingKeyInputFromModifier);
return curKey.squaredDistanceToEdge(x, y) >= keyHysteresisDistanceSquared;
} else { } else {
return true; return true;
} }