From f731eb1760a5693492a34bc11aa755053aa65c19 Mon Sep 17 00:00:00 2001
From: "Tadashi G. Takaoka" <takaoka@google.com>
Date: Sat, 6 Oct 2012 23:22:36 +0900
Subject: [PATCH] Add separate key hysteresis distance for sliding modifier
 input

Bug: 7294402
Change-Id: I78c8be9e1a7b2d49d86bfe1e3a46d1785bfe5d48
---
 java/res/values/attrs.xml                     |  2 +
 java/res/values/config.xml                    |  1 +
 java/res/values/styles.xml                    |  1 +
 .../inputmethod/keyboard/KeyDetector.java     | 22 +++++++++--
 .../keyboard/MainKeyboardView.java            |  5 ++-
 .../inputmethod/keyboard/PointerTracker.java  | 39 ++++++++++---------
 6 files changed, 48 insertions(+), 22 deletions(-)

diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 72dcb0e35f..53051d0334 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -109,6 +109,8 @@
         <attr name="altCodeKeyWhileTypingFadeinAnimator" format="reference" />
         <!-- Key detection hysteresis distance. -->
         <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 -->
         <attr name="touchNoiseThresholdTime" format="integer" />
         <!-- Touch noise threshold distance in millimeter -->
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index 7c57f1f2bf..b3dbb0ee56 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -57,6 +57,7 @@
          Configuration for MainKeyboardView
     -->
     <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>
     <dimen name="config_touch_noise_threshold_distance">12.6dp</dimen>
     <bool name="config_sliding_key_input_enabled">true</bool>
diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml
index 589962c27d..dbb56ab4da 100644
--- a/java/res/values/styles.xml
+++ b/java/res/values/styles.xml
@@ -81,6 +81,7 @@
         <item name="gesturePreviewTrailEndWidth">@dimen/gesture_preview_trail_end_width</item>
         <!-- Common attributes of MainKeyboardView -->
         <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="touchNoiseThresholdDistance">@dimen/config_touch_noise_threshold_distance</item>
         <item name="slidingKeyInputEnable">@bool/config_sliding_key_input_enabled</item>
diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
index f5686dcdab..aa683c1d79 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
@@ -21,6 +21,7 @@ import com.android.inputmethod.latin.Constants;
 
 public class KeyDetector {
     private final int mKeyHysteresisDistanceSquared;
+    private final int mKeyHysteresisDistanceForSlidingModifierSquared;
 
     private Keyboard mKeyboard;
     private int mCorrectionX;
@@ -30,10 +31,24 @@ public class KeyDetector {
      * This class handles key detection.
      *
      * @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) {
+        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);
+        mKeyHysteresisDistanceForSlidingModifierSquared = (int)(
+                keyHysteresisDistanceForSlidingModifier * keyHysteresisDistanceForSlidingModifier);
     }
 
     public void setKeyboard(Keyboard keyboard, float correctionX, float correctionY) {
@@ -45,8 +60,9 @@ public class KeyDetector {
         mKeyboard = keyboard;
     }
 
-    public int getKeyHysteresisDistanceSquared() {
-        return mKeyHysteresisDistanceSquared;
+    public int getKeyHysteresisDistanceSquared(boolean isSlidingFromModifier) {
+        return isSlidingFromModifier
+                ? mKeyHysteresisDistanceForSlidingModifierSquared : mKeyHysteresisDistanceSquared;
     }
 
     public int getTouchX(int x) {
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 20d7847ff6..3e6f92c2a0 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -389,7 +389,10 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
 
         final float keyHysteresisDistance = a.getDimension(
                 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);
         mConfigShowMoreKeysKeyboardAtTouchedPoint = a.getBoolean(
                 R.styleable.MainKeyboardView_showMoreKeysKeyboardAtTouchedPoint, false);
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 7aeddc2798..82c77d6cdf 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -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.
     private boolean mIsShowingMoreKeysPanel;
 
-    // true if this pointer is in sliding key input
+    // true if this pointer is in a sliding key input.
     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;
 
-    // ignore modifier key if true
-    private boolean mIgnoreModifierKey;
-
     // Empty {@link KeyboardActionListener}
     private static final KeyboardActionListener EMPTY_LISTENER =
             new KeyboardActionListener.Adapter();
@@ -383,7 +383,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
         if (sInGesture) {
             return false;
         }
-        final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier();
+        final boolean ignoreModifierKey = mIsInSlidingKeyInputFromModifier && key.isModifier();
         if (DEBUG_LISTENER) {
             Log.d(TAG, String.format("[%d] onPress    : %s%s%s", mPointerId,
                     KeyDetector.printableCode(key),
@@ -407,7 +407,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
     // primaryCode is different from {@link Key#mCode}.
     private void callListenerOnCodeInput(final Key key, final int primaryCode, final int x,
             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 int code = altersCode ? key.getAltCode() : primaryCode;
         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}.
     private void callListenerOnRelease(final Key key, final int primaryCode,
             final boolean withSliding) {
         if (sInGesture) {
             return;
         }
-        final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier();
+        final boolean ignoreModifierKey = mIsInSlidingKeyInputFromModifier && key.isModifier();
         if (DEBUG_LISTENER) {
             Log.d(TAG, String.format("[%d] onRelease  : %s%s%s%s", mPointerId,
                     Keyboard.printableCode(primaryCode),
@@ -778,8 +778,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
                 || mKeyDetector.alwaysAllowsSlidingInput();
         mKeyboardLayoutHasBeenChanged = false;
         mKeyAlreadyProcessed = false;
-        mIsInSlidingKeyInput = false;
-        mIgnoreModifierKey = false;
+        resetSlidingKeyInput();
         if (key != null) {
             // 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
@@ -796,11 +795,16 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
 
     private void startSlidingKeyInput(final Key key) {
         if (!mIsInSlidingKeyInput) {
-            mIgnoreModifierKey = key.isModifier();
+            mIsInSlidingKeyInputFromModifier = key.isModifier();
         }
         mIsInSlidingKeyInput = true;
     }
 
+    private void resetSlidingKeyInput() {
+        mIsInSlidingKeyInput = false;
+        mIsInSlidingKeyInputFromModifier = false;
+    }
+
     private void onGestureMoveEvent(final int x, final int y, final long eventTime,
             final boolean isMajorEvent, final Key key) {
         final int gestureTime = (int)(eventTime - sGestureFirstDownTime);
@@ -847,9 +851,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
             // Register move event on gesture tracker.
             onGestureMoveEvent(x, y, eventTime, true /* isMajorEvent */, key);
             if (sInGesture) {
-                mIgnoreModifierKey = true;
                 mTimerProxy.cancelLongPressTimer();
-                mIsInSlidingKeyInput = true;
                 mCurrentKey = null;
                 setReleasedKeyGraphics(oldKey);
                 return;
@@ -983,7 +985,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
 
     private void onUpEventInternal(final long eventTime) {
         mTimerProxy.cancelKeyTimers();
-        mIsInSlidingKeyInput = false;
+        resetSlidingKeyInput();
         mIsDetectingGesture = false;
         final Key currentKey = mCurrentKey;
         mCurrentKey = null;
@@ -1041,7 +1043,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
     private void onCancelEventInternal() {
         mTimerProxy.cancelKeyTimers();
         setReleasedKeyGraphics(mCurrentKey);
-        mIsInSlidingKeyInput = false;
+        resetSlidingKeyInput();
         if (mIsShowingMoreKeysPanel) {
             mDrawingProxy.dismissMoreKeysPanel();
             mIsShowingMoreKeysPanel = false;
@@ -1070,8 +1072,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
         if (newKey == curKey) {
             return false;
         } else if (curKey != null) {
-            return curKey.squaredDistanceToEdge(x, y)
-                    >= mKeyDetector.getKeyHysteresisDistanceSquared();
+            final int keyHysteresisDistanceSquared = mKeyDetector.getKeyHysteresisDistanceSquared(
+                    mIsInSlidingKeyInputFromModifier);
+            return curKey.squaredDistanceToEdge(x, y) >= keyHysteresisDistanceSquared;
         } else {
             return true;
         }
-- 
GitLab