Merge "Add suggestion span upon starting a gesture." into jb-mr1-dev
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 89b6e7b..0778ad9 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -685,18 +685,13 @@
         if (!sShouldHandleGesture) {
             return;
         }
-        final int activePointerTrackerCount = getActivePointerTrackerCount();
-        if (activePointerTrackerCount == 1) {
-            mIsDetectingGesture = false;
-            // A gesture should start only from the letter key.
-            final boolean isAlphabetKeyboard = (mKeyboard != null)
-                    && mKeyboard.mId.isAlphabetKeyboard();
-            if (isAlphabetKeyboard && !mIsShowingMoreKeysPanel && key != null
-                    && Keyboard.isLetterCode(key.mCode)) {
+        // A gesture should start only from the letter key.
+        mIsDetectingGesture = (mKeyboard != null) && mKeyboard.mId.isAlphabetKeyboard()
+                && !mIsShowingMoreKeysPanel && key != null && Keyboard.isLetterCode(key.mCode);
+        if (mIsDetectingGesture) {
+            if (getActivePointerTrackerCount() == 1) {
                 sGestureFirstDownTime = eventTime;
-                onGestureDownEvent(x, y, eventTime);
             }
-        } else if (sInGesture && activePointerTrackerCount > 1) {
             onGestureDownEvent(x, y, eventTime);
         }
     }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 5712d3b..b8a8f9a 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -715,11 +715,13 @@
             mSpaceState = SPACE_STATE_NONE;
 
             if (mSuggestionStripView != null) {
-                mSuggestionStripView.clear();
+                // This will set the punctuation suggestions if next word suggestion is off;
+                // otherwise it will clear the suggestion strip.
+                setPunctuationSuggestions();
             }
         }
 
-        mConnection.resetCachesUponCursorMove(mLastSelectionStart);
+        mConnection.resetCachesUponCursorMove(editorInfo.initialSelStart);
 
         if (isDifferentTextField) {
             mainKeyboardView.closing();
diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp
index c5f2884..530ac9e 100644
--- a/native/jni/src/proximity_info_state.cpp
+++ b/native/jni/src/proximity_info_state.cpp
@@ -104,6 +104,7 @@
         mLengthCache.clear();
         mDistanceCache.clear();
         mNearKeysVector.clear();
+        mRelativeSpeeds.clear();
     }
     if (DEBUG_GEO_FULL) {
         AKLOGI("Init ProximityInfoState: reused points =  %d, last input size = %d",
@@ -159,6 +160,36 @@
         mInputSize = mInputXs.size();
     }
 
+    if (mInputSize > 0 && isGeometric) {
+        int sumDuration = mTimes.back() - mTimes.front();
+        int sumLength = mLengthCache.back() - mLengthCache.front();
+        float averageSpeed = static_cast<float>(sumLength) / static_cast<float>(sumDuration);
+        mRelativeSpeeds.resize(mInputSize);
+        for (int i = lastSavedInputSize; i < mInputSize; ++i) {
+            const int index = mInputIndice[i];
+            int length = 0;
+            int duration = 0;
+            if (index == 0 && index < inputSize - 1) {
+                length = getDistanceInt(xCoordinates[index], yCoordinates[index],
+                        xCoordinates[index + 1], yCoordinates[index + 1]);
+                duration = times[index + 1] - times[index];
+            } else if (index == inputSize - 1 && index > 0) {
+                length = getDistanceInt(xCoordinates[index - 1], yCoordinates[index - 1],
+                        xCoordinates[index], yCoordinates[index]);
+                duration = times[index] - times[index - 1];
+            } else if (0 < index && index < inputSize - 1) {
+                length = getDistanceInt(xCoordinates[index - 1], yCoordinates[index - 1],
+                        xCoordinates[index + 1], yCoordinates[index + 1]);
+                duration = times[index + 1] - times[index - 1];
+            } else {
+                length = 0;
+                duration = 1;
+            }
+            const float speed = static_cast<float>(length) / static_cast<float>(duration);
+            mRelativeSpeeds[i] = speed / averageSpeed;
+        }
+    }
+
     if (mInputSize > 0) {
         const int keyCount = mProximityInfo->getKeyCount();
         mNearKeysVector.resize(mInputSize);
@@ -464,7 +495,7 @@
 }
 
 int ProximityInfoState::getDuration(const int index) const {
-    if (mInputSize > 0 && index >= 0 && index < mInputSize - 1) {
+    if (index >= 0 && index < mInputSize - 1) {
         return mTimes[index + 1] - mTimes[index];
     }
     return 0;
@@ -524,13 +555,6 @@
     return newFilterSize;
 }
 
-float ProximityInfoState::getAveragePointDuration() const {
-    if (mInputSize == 0) {
-        return 0.0f;
-    }
-    return static_cast<float>(mTimes[mInputSize - 1] - mTimes[0]) / static_cast<float>(mInputSize);
-}
-
 void ProximityInfoState::popInputData() {
     mInputXs.pop_back();
     mInputYs.pop_back();
diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/proximity_info_state.h
index 48862a7..c1ec76c 100644
--- a/native/jni/src/proximity_info_state.h
+++ b/native/jni/src/proximity_info_state.h
@@ -55,7 +55,7 @@
               mHasTouchPositionCorrectionData(false), mMostCommonKeyWidthSquare(0), mLocaleStr(),
               mKeyCount(0), mCellHeight(0), mCellWidth(0), mGridHeight(0), mGridWidth(0),
               mIsContinuationPossible(false), mInputXs(), mInputYs(), mTimes(), mInputIndice(),
-              mDistanceCache(), mLengthCache(), mNearKeysVector(),
+              mDistanceCache(), mLengthCache(), mRelativeSpeeds(), mNearKeysVector(),
               mTouchPositionCorrectionEnabled(false), mInputSize(0) {
         memset(mInputCodes, 0, sizeof(mInputCodes));
         memset(mNormalizedSquaredDistances, 0, sizeof(mNormalizedSquaredDistances));
@@ -220,7 +220,9 @@
     int32_t getAllPossibleChars(
             const size_t startIndex, int32_t *const filter, const int32_t filterSize) const;
 
-    float getAveragePointDuration() const;
+    float getRelativeSpeed(const int index) const {
+        return mRelativeSpeeds[index];
+    }
  private:
     DISALLOW_COPY_AND_ASSIGN(ProximityInfoState);
     typedef hash_map_compat<int, float> NearKeysDistanceMap;
@@ -283,6 +285,7 @@
     std::vector<int> mInputIndice;
     std::vector<float> mDistanceCache;
     std::vector<int>  mLengthCache;
+    std::vector<float> mRelativeSpeeds;
     std::vector<NearKeycodesSet> mNearKeysVector;
     bool mTouchPositionCorrectionEnabled;
     int32_t mInputCodes[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL];