Other improvements to text cursor movement.

Paste happened on pressed position instead of current cursor location
when triggered by a long touch.

Change-Id: I86900f2bbb93390d3efa756aeebb424c4ae7e19b
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 44b14e7..138aefa 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6551,7 +6551,10 @@
             if (!mFrozenWithFocus || (selStart < 0 || selEnd < 0)) {
                 // If a tap was used to give focus to that view, move cursor at tap position.
                 // Has to be done before onTakeFocus, which can be overloaded.
-                moveCursorToLastTapPosition();
+                final int lastTapPosition = getLastTapPosition();
+                if (lastTapPosition >= 0) {
+                    Selection.setSelection((Spannable) mText, lastTapPosition);
+                }
 
                 if (mMovement != null) {
                     mMovement.onTakeFocus(this, (Spannable) mText, direction);
@@ -6610,6 +6613,10 @@
             } else {
                 terminateTextSelectionMode();
             }
+
+            if (mSelectionModifierCursorController != null) {
+                ((SelectionModifierCursorController) mSelectionModifierCursorController).resetTouchOffsets();
+            }
         }
 
         startStopMarquee(focused);
@@ -6621,20 +6628,22 @@
         super.onFocusChanged(focused, direction, previouslyFocusedRect);
     }
 
-    private void moveCursorToLastTapPosition() {
+    private int getLastTapPosition() {
         if (mSelectionModifierCursorController != null) {
-            int mTapToFocusPosition = ((SelectionModifierCursorController)
+            int lastTapPosition = ((SelectionModifierCursorController)
                     mSelectionModifierCursorController).getMinTouchOffset();
-            if (mTapToFocusPosition >= 0) {
+            if (lastTapPosition >= 0) {
                 // Safety check, should not be possible.
-                if (mTapToFocusPosition > mText.length()) {
-                    Log.e(LOG_TAG, "Invalid tap focus position (" + mTapToFocusPosition + " vs "
+                if (lastTapPosition > mText.length()) {
+                    Log.e(LOG_TAG, "Invalid tap focus position (" + lastTapPosition + " vs "
                             + mText.length() + ")");
-                    mTapToFocusPosition = mText.length();
+                    lastTapPosition = mText.length();
                 }
-                Selection.setSelection((Spannable) mText, mTapToFocusPosition);
+                return lastTapPosition;
             }
         }
+
+        return -1;
     }
 
     @Override
@@ -7297,10 +7306,8 @@
     }
     
     private String getWordForDictionary() {
-        if (!mContextMenuTriggeredByKey) {
-            moveCursorToLastTapPosition();
-        }
-        long wordLimits = getWordLimitsAt(getSelectionStart());
+        int seedPosition = mContextMenuTriggeredByKey ? getSelectionStart() : getLastTapPosition();
+        long wordLimits = getWordLimitsAt(seedPosition);
         if (wordLimits >= 0) {
             int start = extractRangeStartFromLong(wordLimits);
             int end = extractRangeEndFromLong(wordLimits);
@@ -8019,7 +8026,7 @@
         SelectionModifierCursorController() {
             mStartHandle = new HandleView(this, HandleView.LEFT);
             mEndHandle = new HandleView(this, HandleView.RIGHT);
-            mMinTouchOffset = mMaxTouchOffset = -1;
+            resetTouchOffsets();
         }
 
         public void show() {
@@ -8151,6 +8158,10 @@
             return mMaxTouchOffset;
         }
 
+        public void resetTouchOffsets() {
+            mMinTouchOffset = mMaxTouchOffset = -1;
+        }
+
         /**
          * @return true iff this controller is currently used to move the selection start.
          */