scroll text field with touch

Add a hidden public method to text/method/Touch.java that
computes the maximum scroll amount for a text field.

Remove 'faketouch' code; it causes a crash and is
no longer required.

Pass the percentage of the current scroll from the UI
thread to webkit. One additional fix is to allow very
small movements which are currently disallowed because
they are smaller than 'smallerSlop' in WebTextView.java.

Companion fix is in external/webkit.

Fixes http://b/issue?id=2133049
diff --git a/core/java/android/text/method/Touch.java b/core/java/android/text/method/Touch.java
index dfc16f5..6995107 100644
--- a/core/java/android/text/method/Touch.java
+++ b/core/java/android/text/method/Touch.java
@@ -72,6 +72,24 @@
     }
 
     /**
+     * @hide
+     * Returns the maximum scroll value in x.
+     */
+    public static int getMaxScrollX(TextView widget, Layout layout, int y) {
+        int top = layout.getLineForVertical(y);
+        int bottom = layout.getLineForVertical(y + widget.getHeight()
+                - widget.getTotalPaddingTop() -widget.getTotalPaddingBottom());
+        int left = Integer.MAX_VALUE;
+        int right = 0;
+        for (int i = top; i <= bottom; i++) {
+            left = (int) Math.min(left, layout.getLineLeft(i));
+            right = (int) Math.max(right, layout.getLineRight(i));
+        }
+        return right - left - widget.getWidth() - widget.getTotalPaddingLeft()
+                - widget.getTotalPaddingRight();
+    }
+
+    /**
      * Handles touch events for dragging.  You may want to do other actions
      * like moving the cursor on touch as well.
      */
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 65ce158..f479124 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -276,25 +276,6 @@
     }
 
     /**
-     *  Create a fake touch up event at (x,y) with respect to this WebTextView.
-     *  This is used by WebView to act as though a touch event which happened
-     *  before we placed the WebTextView actually hit it, so that it can place
-     *  the cursor accordingly.
-     */
-    /* package */ void fakeTouchEvent(float x, float y) {
-        // We need to ensure that there is a Layout, since the Layout is used
-        // in determining where to place the cursor.
-        if (getLayout() == null) {
-            measure(mWidthSpec, mHeightSpec);
-        }
-        // Create a fake touch up, which is used to place the cursor.
-        MotionEvent ev = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP,
-                x, y, 0);
-        onTouchEvent(ev);
-        ev.recycle();
-    }
-
-    /**
      *  Determine whether this WebTextView currently represents the node
      *  represented by ptr.
      *  @param  ptr Pointer to a node to compare to.
@@ -457,7 +438,14 @@
             int smallerSlop = slop/2;
             if (dx > smallerSlop || dy > smallerSlop) {
                 if (mWebView != null) {
-                    mWebView.scrollFocusedTextInput(mScrollX, mScrollY);
+                    float maxScrollX = (float) Touch.getMaxScrollX(this,
+                                getLayout(), mScrollY);
+                    if (DebugFlags.WEB_TEXT_VIEW) {
+                        Log.v(LOGTAG, "onTouchEvent x=" + mScrollX + " y="
+                                + mScrollY + " maxX=" + maxScrollX);
+                    }
+                    mWebView.scrollFocusedTextInput(maxScrollX > 0 ?
+                            mScrollX / maxScrollX : 0, mScrollY);
                 }
                 mScrolled = true;
                 return true;
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index eb6e0f1..9d86733 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -3007,17 +3007,6 @@
             if (mWebTextView == null) return;
 
             imm.showSoftInput(mWebTextView, 0);
-            // Now we need to fake a touch event to place the cursor where the
-            // user touched.
-            AbsoluteLayout.LayoutParams lp = (AbsoluteLayout.LayoutParams)
-                    mWebTextView.getLayoutParams();
-            if (lp != null) {
-                // Take the last touch and adjust for the location of the
-                // WebTextView.
-                float x = mLastTouchX + (float) (mScrollX - lp.x);
-                float y = mLastTouchY + (float) (mScrollY - lp.y);
-                mWebTextView.fakeTouchEvent(x, y);
-            }
             if (mInZoomOverview) {
                 // if in zoom overview mode, call doDoubleTap() to bring it back
                 // to normal mode so that user can enter text.
@@ -4505,18 +4494,19 @@
 
     /**
      * Scroll the focused text field/area to match the WebTextView
-     * @param x New x position of the WebTextView in view coordinates
+     * @param xPercent New x position of the WebTextView from 0 to 1.
      * @param y New y position of the WebTextView in view coordinates
      */
-    /*package*/ void scrollFocusedTextInput(int x, int y) {
+    /*package*/ void scrollFocusedTextInput(float xPercent, int y) {
         if (!inEditingMode() || mWebViewCore == null) {
             return;
         }
-        mWebViewCore.sendMessage(EventHub.SCROLL_TEXT_INPUT, viewToContentX(x),
+        mWebViewCore.sendMessage(EventHub.SCROLL_TEXT_INPUT,
                 // Since this position is relative to the top of the text input
                 // field, we do not need to take the title bar's height into
                 // consideration.
-                viewToContentDimension(y));
+                viewToContentDimension(y),
+                new Float(xPercent));
     }
 
     /**
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 8b6746e..e2aa1d0 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -872,7 +872,8 @@
                             break;
 
                         case SCROLL_TEXT_INPUT:
-                            nativeScrollFocusedTextInput(msg.arg1, msg.arg2);
+                            nativeScrollFocusedTextInput(
+                                    ((Float) msg.obj).floatValue(), msg.arg1);
                             break;
 
                         case LOAD_URL:
@@ -2076,9 +2077,9 @@
     private native void nativeUpdateFrameCacheIfLoading();
 
     /**
-     * Scroll the focused textfield to (x, y) in document space
+     * Scroll the focused textfield to (xPercent, y) in document space
      */
-    private native void nativeScrollFocusedTextInput(int x, int y);
+    private native void nativeScrollFocusedTextInput(float xPercent, int y);
 
     // these must be in document space (i.e. not scaled/zoomed).
     private native void nativeSetScrollOffset(int gen, int dx, int dy);