Merge "Fix a bug in multiple shortcut handling code." into jb-mr1-dev
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index b3dbb0e..32b5444 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -81,7 +81,7 @@
     <integer name="config_gesture_dynamic_time_threshold_to">20</integer>
     <!-- Distance based threshold values for gesture detection (keyWidth%/sec) -->
     <fraction name="config_gesture_dynamic_distance_threshold_from">600%</fraction>
-    <fraction name="config_gesture_dynamic_distance_threshold_to">35%</fraction>
+    <fraction name="config_gesture_dynamic_distance_threshold_to">50%</fraction>
     <!-- Parameter for gesture sampling (keyWidth%/sec) -->
     <fraction name="config_gesture_sampling_minimum_distance">16.6666%</fraction>
     <!-- Parameters for gesture recognition (msec) and (keyWidth%/sec) -->
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 82c77d6..3610533 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -192,47 +192,32 @@
                     gestureStrokeParams.mStaticTimeThresholdAfterFastTyping;
         }
 
-        private void recordTyping(final long eventTime) {
-            mLastTypingTime = eventTime;
-        }
-
-        private void recordLetterTyping(final long eventTime) {
-            mLastLetterTypingTime = eventTime;
-            // Reset gesture typing time
-            mLastBatchInputTime = 0;
-        }
-
-        private void recordGestureTyping(final long eventTime) {
-            mLastBatchInputTime = eventTime;
-            // Reset typing time.
-            mLastTypingTime = 0;
-        }
-
-        private boolean isInTyping() {
-            return mLastTypingTime != 0;
-        }
-
-        private boolean isInBatchInput() {
-            return mLastBatchInputTime != 0;
+        private boolean wasLastInputTyping() {
+            return mLastTypingTime >= mLastBatchInputTime;
         }
 
         public void onCodeInput(final int code, final long eventTime) {
-            if (Keyboard.isLetterCode(code) && code != Keyboard.CODE_SPACE) {
-                if (isInTyping()
-                        && eventTime - mLastTypingTime < mStaticTimeThresholdAfterFastTyping) {
-                    recordLetterTyping(eventTime);
+            // Record the letter typing time when
+            // 1. Letter keys are typed successively without any batch input in between.
+            // 2. A letter key is typed within the threshold time since the last any key typing.
+            // 3. A non-letter key is typed within the threshold time since the last letter key
+            // typing.
+            if (Character.isLetter(code)) {
+                if (wasLastInputTyping()
+                        || eventTime - mLastTypingTime < mStaticTimeThresholdAfterFastTyping) {
+                    mLastLetterTypingTime = eventTime;
                 }
             } else {
                 if (eventTime - mLastLetterTypingTime < mStaticTimeThresholdAfterFastTyping) {
                     // This non-letter typing should be treated as a part of fast typing.
-                    recordLetterTyping(eventTime);
+                    mLastLetterTypingTime = eventTime;
                 }
             }
-            recordTyping(eventTime);
+            mLastTypingTime = eventTime;
         }
 
         public void onEndBatchInput(final long eventTime) {
-            recordGestureTyping(eventTime);
+            mLastBatchInputTime = eventTime;
         }
 
         public long getLastLetterTypingTime() {
@@ -240,7 +225,7 @@
         }
 
         public boolean needsToSuppressKeyPreviewPopup(final long eventTime) {
-            return !isInTyping() && isInBatchInput()
+            return !wasLastInputTyping()
                     && eventTime - mLastBatchInputTime < mSuppressKeyPreviewAfterBatchInputDuration;
         }
     }
@@ -851,11 +836,13 @@
             // Register move event on gesture tracker.
             onGestureMoveEvent(x, y, eventTime, true /* isMajorEvent */, key);
             if (sInGesture) {
-                mTimerProxy.cancelLongPressTimer();
                 mCurrentKey = null;
                 setReleasedKeyGraphics(oldKey);
                 return;
             }
+            if (mGestureStrokeWithPreviewPoints.hasDetectedFastMove()) {
+                mTimerProxy.cancelLongPressTimer();
+            }
         }
 
         if (key != null) {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java
index 9b1a201..c406f0c 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java
@@ -190,8 +190,8 @@
         return mParams.mDynamicTimeThresholdFrom - decayedThreshold;
     }
 
-    public boolean isStartOfAGesture() {
-        if (mDetectFastMoveTime == 0) {
+    public final boolean isStartOfAGesture() {
+        if (!hasDetectedFastMove()) {
             return false;
         }
         final int size = mEventTimes.getLength();
@@ -200,6 +200,9 @@
         }
         final int lastIndex = size - 1;
         final int deltaTime = mEventTimes.get(lastIndex) - mDetectFastMoveTime;
+        if (deltaTime < 0) {
+            return false;
+        }
         final int deltaDistance = getDistance(
                 mXCoordinates.get(lastIndex), mYCoordinates.get(lastIndex),
                 mDetectFastMoveX, mDetectFastMoveY);
@@ -240,6 +243,10 @@
         mLastMajorEventY = y;
     }
 
+    public final boolean hasDetectedFastMove() {
+        return mDetectFastMoveTime > 0;
+    }
+
     private int detectFastMove(final int x, final int y, final int time) {
         final int size = mEventTimes.getLength();
         final int lastIndex = size - 1;
@@ -255,7 +262,7 @@
                 Log.d(TAG, String.format("[%d] detectFastMove: speed=%5.2f", mPointerId, speed));
             }
             // Equivalent to (pixels / msecs < mStartSpeedThreshold / MSEC_PER_SEC)
-            if (mDetectFastMoveTime == 0 && pixelsPerSec > mDetectFastMoveSpeedThreshold * msecs) {
+            if (!hasDetectedFastMove() && pixelsPerSec > mDetectFastMoveSpeedThreshold * msecs) {
                 if (DEBUG) {
                     final float speed = (float)pixelsPerSec / msecs / mKeyWidth;
                     Log.d(TAG, String.format(
@@ -306,11 +313,11 @@
         return currentTime > lastRecognitionTime + mParams.mRecognitionMinimumTime;
     }
 
-    public void appendAllBatchPoints(final InputPointers out) {
+    public final void appendAllBatchPoints(final InputPointers out) {
         appendBatchPoints(out, mEventTimes.getLength());
     }
 
-    public void appendIncrementalBatchPoints(final InputPointers out) {
+    public final void appendIncrementalBatchPoints(final InputPointers out) {
         appendBatchPoints(out, mIncrementalRecognitionSize);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
index fa9f79e..201a101 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
@@ -350,7 +350,7 @@
     // of the dictionary would lose whitelist functionality.
     private static boolean hackCanUseDictionaryFile(final Locale locale, final File f) {
         // Only for English - other languages didn't have a whitelist, hence this
-        // ad-hock ## HACK ##
+        // ad-hoc ## HACK ##
         if (!Locale.ENGLISH.getLanguage().equals(locale.getLanguage())) return true;
 
         FileInputStream inStream = null;
diff --git a/tools/dicttool/src/android/inputmethod/latin/dicttool/XmlDictInputOutput.java b/tools/dicttool/src/android/inputmethod/latin/dicttool/XmlDictInputOutput.java
index c31cd72..252c3d6 100644
--- a/tools/dicttool/src/android/inputmethod/latin/dicttool/XmlDictInputOutput.java
+++ b/tools/dicttool/src/android/inputmethod/latin/dicttool/XmlDictInputOutput.java
@@ -93,7 +93,7 @@
             final FusionDictionary dict = mDictionary;
             for (final String shortcutOnly : mShortcutsMap.keySet()) {
                 if (dict.hasWord(shortcutOnly)) continue;
-                dict.add(shortcutOnly, 0, mShortcutsMap.get(shortcutOnly), true /* isNotAWord */);
+                dict.add(shortcutOnly, 1, mShortcutsMap.get(shortcutOnly), true /* isNotAWord */);
             }
             mDictionary = null;
             mShortcutsMap.clear();