Add separate key hysteresis distance for sliding modifier input
Bug: 7294402 Change-Id: I78c8be9e1a7b2d49d86bfe1e3a46d1785bfe5d48main
parent
448e732272
commit
f731eb1760
|
@ -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 -->
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue