Merge "Telephony: Fix config to reflect the correct CM conn type."
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 9002b1d..72b70bc 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1039,7 +1039,7 @@
      *
      * @return true if the popup is translated upwards to fit on screen
      */
-    boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p,
+    private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p,
             int xoff, int yoff) {
 
         anchor.getLocationInWindow(mDrawingLocation);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 09c1ac5..70d71fb 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4498,8 +4498,6 @@
         */
 
         canvas.restore();
-
-        updateCursorControllerPositions();
     }
 
     private void updateCursorsPositions() {
@@ -4557,15 +4555,7 @@
      * @hide
      */
     protected void updateCursorControllerPositions() {
-        // No need to create the controllers if they were not already
-        if (mInsertionPointCursorController != null &&
-                mInsertionPointCursorController.isShowing()) {
-            mInsertionPointCursorController.updatePosition();
-        }
-        if (mSelectionModifierCursorController != null &&
-                mSelectionModifierCursorController.isShowing()) {
-            mSelectionModifierCursorController.updatePosition();
-        }
+        // TODO remove
     }
 
     @Override
@@ -6285,15 +6275,15 @@
         }
 
         if (isFocused()) {
-            // This offsets because getInterestingRect() is in terms of
-            // viewport coordinates, but requestRectangleOnScreen()
-            // is in terms of content coordinates.
+            // This offsets because getInterestingRect() is in terms of viewport coordinates, but
+            // requestRectangleOnScreen() is in terms of content coordinates.
 
-            Rect r = new Rect(x, top, x + 1, bottom);
-            getInterestingRect(r, line);
-            r.offset(mScrollX, mScrollY);
+            if (mTempRect == null) mTempRect = new Rect();
+            mTempRect.set(x, top, x + 1, bottom);
+            getInterestingRect(mTempRect, line);
+            mTempRect.offset(mScrollX, mScrollY);
 
-            if (requestRectangleOnScreen(r)) {
+            if (requestRectangleOnScreen(mTempRect)) {
                 changed = true;
             }
         }
@@ -7356,14 +7346,9 @@
             }
 
             if (isTextEditable() || mTextIsSelectable) {
-                if (mScrollX != oldScrollX || mScrollY != oldScrollY) {
+                if (mScrollX != oldScrollX || mScrollY != oldScrollY) { // TODO remove
                     // Hide insertion anchor while scrolling. Leave selection.
-                    hideInsertionPointCursorController();
-                    // No need to create the controller, since there is nothing to update.
-                    if (mSelectionModifierCursorController != null &&
-                            mSelectionModifierCursorController.isShowing()) {
-                        mSelectionModifierCursorController.updatePosition();
-                    }
+                    hideInsertionPointCursorController(); // TODO any motion should hide it
                 }
 
                 if (touchIsFinished) {
@@ -7373,7 +7358,6 @@
                         handled |= imm != null && imm.showSoftInput(this, 0);
                     }
 
-
                     boolean selectAllGotFocus = mSelectAllOnFocus && didTouchFocusSelect();
                     if (!selectAllGotFocus && hasSelection()) {
                         startSelectionActionMode();
@@ -8653,26 +8637,31 @@
         }
     }
 
-    private class HandleView extends View implements ViewTreeObserver.OnScrollChangedListener {
+    private class HandleView extends View implements ViewTreeObserver.OnPreDrawListener {
         private Drawable mDrawable;
-        private final ScrollingPopupWindow mContainer;
-        private int mPositionX;
-        private int mPositionY;
+        private final PopupWindow mContainer;
+        // Position with respect to the parent TextView
+        private int mPositionX, mPositionY;
         private final CursorController mController;
         private boolean mIsDragging;
-        private float mTouchToWindowOffsetX;
-        private float mTouchToWindowOffsetY;
+        // Offset from touch position to mPosition
+        private float mTouchToWindowOffsetX, mTouchToWindowOffsetY;
         private float mHotspotX;
         // Offsets the hotspot point up, so that cursor is not hidden by the finger when moving up
         private float mTouchOffsetY;
         // Where the touch position should be on the handle to ensure a maximum cursor visibility
         private float mIdealVerticalOffset;
-        private int mLastParentX;
-        private int mLastParentY;
+        // Parent's (TextView) position in window
+        private int mLastParentX, mLastParentY;
         private float mDownPositionX, mDownPositionY;
+        // PopupWindow container absolute position with respect to the enclosing window
         private int mContainerPositionX, mContainerPositionY;
-        private long mTouchTimer;
+        // Visible or not (scrolled off screen), whether or not this handle should be visible
+        private boolean mIsActive = false;
+        // The insertion handle can have an associated PastePopupMenu
         private boolean mIsInsertionHandle = false;
+        // Used to detect taps on the insertion handle, which will affect the PastePopupMenu
+        private long mTouchTimer;
         private PastePopupMenu mPastePopupWindow;
 
         // Touch-up filter: number of previous positions remembered
@@ -8684,12 +8673,12 @@
         private int mPreviousOffsetIndex = 0;
         private int mNumberPreviousOffsets = 0;
 
-        public void startTouchUpFilter(int offset) {
+        private void startTouchUpFilter(int offset) {
             mNumberPreviousOffsets = 0;
             addPositionToTouchUpFilter(offset);
         }
 
-        public void addPositionToTouchUpFilter(int offset) {
+        private void addPositionToTouchUpFilter(int offset) {
             if (mNumberPreviousOffsets > 0 &&
                     mPreviousOffsets[mPreviousOffsetIndex] == offset) {
                 // Make sure only actual changes of position are recorded.
@@ -8702,7 +8691,7 @@
             mNumberPreviousOffsets++;
         }
 
-        public void filterOnTouchUp() {
+        private void filterOnTouchUp() {
             final long now = SystemClock.uptimeMillis();
             int i = 0;
             int index = mPreviousOffsetIndex;
@@ -8725,16 +8714,17 @@
         public HandleView(CursorController controller, int pos) {
             super(TextView.this.mContext);
             mController = controller;
-            mContainer = new ScrollingPopupWindow(TextView.this.mContext, null,
+            mContainer = new PopupWindow(TextView.this.mContext, null,
                     com.android.internal.R.attr.textSelectHandleWindowStyle);
             mContainer.setSplitTouchEnabled(true);
             mContainer.setClippingEnabled(false);
             mContainer.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
+            mContainer.setContentView(this);
 
-            setOrientation(pos);
+            setPosition(pos);
         }
 
-        public void setOrientation(int pos) {
+        private void setPosition(int pos) {
             int handleWidth;
             switch (pos) {
                 case LEFT: {
@@ -8774,38 +8764,48 @@
             }
 
             final int handleHeight = mDrawable.getIntrinsicHeight();
-
             mTouchOffsetY = -0.3f * handleHeight;
             mIdealVerticalOffset = 0.7f * handleHeight;
+
             invalidate();
         }
 
         @Override
         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            setMeasuredDimension(mDrawable.getIntrinsicWidth(),
-                    mDrawable.getIntrinsicHeight());
+            setMeasuredDimension(mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
         }
 
         public void show() {
-            if (!isPositionVisible()) {
-                hide();
-                return;
-            }
-            mContainer.setContentView(this);
-            mContainerPositionX = mPositionX;
-            mContainerPositionY = mPositionY - TextView.this.getHeight();
-            mContainer.showAsDropDown(TextView.this, mContainerPositionX, mContainerPositionY);
+            updateContainerPosition();
+            if (isShowing()) {
+                mContainer.update(mContainerPositionX, mContainerPositionY,
+                        mRight - mLeft, mBottom - mTop);
 
-            // Hide paste view when handle is moved on screen.
+                hidePastePopupWindow();
+            } else {
+                mContainer.showAtLocation(TextView.this, 0,
+                        mContainerPositionX, mContainerPositionY);
+
+                mIsActive = true;
+
+                ViewTreeObserver vto = TextView.this.getViewTreeObserver();
+                vto.addOnPreDrawListener(this);
+            }
+        }
+
+        private void dismiss() {
+            mIsDragging = false;
+            mContainer.dismiss();
             hidePastePopupWindow();
         }
 
         public void hide() {
-            mIsDragging = false;
-            mContainer.dismiss();
-            hidePastePopupWindow();
+            dismiss();
+
+            mIsActive = false;
+
             ViewTreeObserver vto = TextView.this.getViewTreeObserver();
-            vto.removeOnScrollChangedListener(this);
+            vto.removeOnPreDrawListener(this);
         }
 
         public boolean isShowing() {
@@ -8829,9 +8829,7 @@
 
             final TextView hostView = TextView.this;
 
-            if (mTempRect == null) {
-                mTempRect = new Rect();
-            }
+            if (mTempRect == null) mTempRect = new Rect();
             final Rect clip = mTempRect;
             clip.left = compoundPaddingLeft;
             clip.top = extendedPaddingTop;
@@ -8856,44 +8854,59 @@
         private void moveTo(int x, int y) {
             mPositionX = x - TextView.this.mScrollX;
             mPositionY = y - TextView.this.mScrollY;
-            if (isPositionVisible()) {
-                int[] coords = null;
-                if (mContainer.isShowing()) {
-                    final int containerPositionX = mPositionX;
-                    final int containerPositionY = mPositionY - TextView.this.getHeight();
 
-                    if (containerPositionX != mContainerPositionX || 
-                        containerPositionY != mContainerPositionY) {
-                        mContainerPositionX = containerPositionX;
-                        mContainerPositionY = containerPositionY;
+            if (mIsDragging) {
+                TextView.this.getLocationInWindow(mTempCoords);
+                if (mTempCoords[0] != mLastParentX || mTempCoords[1] != mLastParentY) {
+                    mTouchToWindowOffsetX += mTempCoords[0] - mLastParentX;
+                    mTouchToWindowOffsetY += mTempCoords[1] - mLastParentY;
+                    mLastParentX = mTempCoords[0];
+                    mLastParentY = mTempCoords[1];
+                }
+                // Hide paste popup window as soon as the handle is dragged.
+                hidePastePopupWindow();
+            }
+        }
 
-                        mContainer.update(TextView.this, mContainerPositionX, mContainerPositionY,
-                                mRight - mLeft, mBottom - mTop);
+        /**
+         * Updates the global container's position.
+         * @return whether or not the position has actually changed
+         */
+        private boolean updateContainerPosition() {
+            // TODO Prevent this using different HandleView subclasses
+            mController.updateOffset(this, mController.getCurrentOffset(this));
+            TextView.this.getLocationInWindow(mTempCoords);
+            final int containerPositionX = mTempCoords[0] + mPositionX;
+            final int containerPositionY = mTempCoords[1] + mPositionY;
 
-                        // Hide paste popup window as soon as a scroll occurs.
-                        hidePastePopupWindow();
+            if (containerPositionX != mContainerPositionX ||
+                containerPositionY != mContainerPositionY) {
+                mContainerPositionX = containerPositionX;
+                mContainerPositionY = containerPositionY;
+                return true;
+            }
+            return false;
+        }
+
+        public boolean onPreDraw() {
+            if (updateContainerPosition()) {
+                if (isPositionVisible()) {
+                    mContainer.update(mContainerPositionX, mContainerPositionY,
+                            mRight - mLeft, mBottom - mTop);
+
+                    if (mIsActive && !isShowing()) {
+                        show();
                     }
                 } else {
-                    show();
+                    if (isShowing()) {
+                        dismiss();
+                    }
                 }
 
-                if (mIsDragging) {
-                    if (coords == null) {
-                        coords = mTempCoords;
-                        TextView.this.getLocationInWindow(coords);
-                    }
-                    if (coords[0] != mLastParentX || coords[1] != mLastParentY) {
-                        mTouchToWindowOffsetX += coords[0] - mLastParentX;
-                        mTouchToWindowOffsetY += coords[1] - mLastParentY;
-                        mLastParentX = coords[0];
-                        mLastParentY = coords[1];
-                    }
-                    // Hide paste popup window as soon as the handle is dragged.
-                    hidePastePopupWindow();
-                }
-            } else {
-                hide();
+                // Hide paste popup as soon as the view is scrolled or moved
+                hidePastePopupWindow();
             }
+            return true;
         }
 
         @Override
@@ -8979,7 +8992,7 @@
             return mIsDragging;
         }
 
-        void positionAtCursor(final int offset) {
+        void positionAtCursor(int offset) {
             addPositionToTouchUpFilter(offset);
             final int width = mDrawable.getIntrinsicWidth();
             final int height = mDrawable.getIntrinsicHeight();
@@ -9013,50 +9026,6 @@
                 mPastePopupWindow.hide();
             }
         }
-
-        /**
-         * A popup window, attached to a view, and that listens to scroll events in its anchors'
-         * view hierarchy, so that it is automatically moved on such events.
-         */
-        private class ScrollingPopupWindow extends PopupWindow {
-
-            private int[] mDrawingLocations = new int[2];
-
-            public ScrollingPopupWindow(Context context, AttributeSet attrs, int defStyle) {
-                super(context, attrs, defStyle);
-            }
-
-            @Override
-            public boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p,
-                    int xoff, int yoff) {
-                anchor.getLocationInWindow(mDrawingLocations);
-                p.x = mDrawingLocations[0] + xoff;
-                p.y = mDrawingLocations[1] + anchor.getHeight() + yoff;
-
-                // Hide paste popup as soon as the view is scrolled.
-                hidePastePopupWindow();
-
-                if (!isPositionVisible()) {
-                    dismiss();
-                    onHandleBecomeInvisible();
-                }
-
-                return false;
-            }
-        }
-
-        public void onScrollChanged() {
-            if (isPositionVisible()) {
-                show();
-                ViewTreeObserver vto = TextView.this.getViewTreeObserver();
-                vto.removeOnScrollChangedListener(this);
-            }
-        }
-
-        public void onHandleBecomeInvisible() {
-            ViewTreeObserver vto = TextView.this.getViewTreeObserver();
-            vto.addOnScrollChangedListener(this);
-        }
     }
 
     private class InsertionPointCursorController implements CursorController {
@@ -9074,7 +9043,7 @@
         }
 
         public void show(int delayBeforePaste) {
-            updatePosition();
+            getHandle().show();
             hideDelayed();
             removePastePopupCallback();
             final long durationSinceCutOrCopy = SystemClock.uptimeMillis() - sLastCutOrCopyTime;
@@ -9213,7 +9182,6 @@
             if (mEndHandle == null) mEndHandle = new HandleView(this, HandleView.RIGHT);
 
             mIsShowing = true;
-            updatePosition();
 
             mStartHandle.show();
             mEndHandle.show();