Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2bbe178f authored by Gilles Debunne's avatar Gilles Debunne Committed by Android (Google) Code Review
Browse files

Merge "Text selection handles correctly scroll"

parents beefeb61 81f08086
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -378,8 +378,7 @@ public class PopupWindow {
     * <p>Change the popup's content. The content is represented by an instance
     * of {@link android.view.View}.</p>
     *
     * <p>This method has no effect if called when the popup is showing.  To
     * apply it while a popup is showing, call </p>
     * <p>This method has no effect if called when the popup is showing.</p>
     *
     * @param contentView the new content for the popup
     *
@@ -1040,7 +1039,7 @@ public class PopupWindow {
     *
     * @return true if the popup is translated upwards to fit on screen
     */
    private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p,
    boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p,
            int xoff, int yoff) {

        anchor.getLocationInWindow(mDrawingLocation);
@@ -1374,6 +1373,7 @@ public class PopupWindow {
     * height can be set to -1 to update location only.  Calling this function
     * also updates the window with the current popup state as
     * described for {@link #update()}.</p>
     *
     * <p>If the view later scrolls to move <code>anchor</code> to a different
     * location, the popup will be moved correspondingly.</p>
     *
@@ -1395,9 +1395,13 @@ public class PopupWindow {
        }

        WeakReference<View> oldAnchor = mAnchor;
        if (oldAnchor == null || oldAnchor.get() != anchor ||
                (updateLocation && (mAnchorXoff != xoff || mAnchorYoff != yoff))) {
        final boolean needsUpdate = updateLocation && (mAnchorXoff != xoff || mAnchorYoff != yoff);
        if (oldAnchor == null || oldAnchor.get() != anchor || (needsUpdate && !mIsDropdown)) {
            registerForScrollChanged(anchor, xoff, yoff);
        } else if (needsUpdate) {
            // No need to register again if this is a DropDown, showAsDropDown already did.
            mAnchorXoff = xoff;
            mAnchorYoff = yoff;
        }

        WindowManager.LayoutParams p = (WindowManager.LayoutParams) mPopupView.getLayoutParams();
+92 −72
Original line number Diff line number Diff line
@@ -3873,9 +3873,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener

    private void registerForPreDraw() {
        final ViewTreeObserver observer = getViewTreeObserver();
        if (observer == null) {
            return;
        }

        if (mPreDrawState == PREDRAW_NOT_REGISTERED) {
            observer.addOnPreDrawListener(this);
@@ -3961,7 +3958,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        }

        final ViewTreeObserver observer = getViewTreeObserver();
        if (observer != null) {
        // No need to create the controller.
        // The get method will add the listener on controller creation.
        if (mInsertionPointCursorController != null) {
@@ -3971,14 +3967,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            observer.addOnTouchModeChangeListener(mSelectionModifierCursorController);
        }
    }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();

        final ViewTreeObserver observer = getViewTreeObserver();
        if (observer != null) {
        if (mPreDrawState != PREDRAW_NOT_REGISTERED) {
            observer.removeOnPreDrawListener(this);
            mPreDrawState = PREDRAW_NOT_REGISTERED;
@@ -3990,7 +3984,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        if (mSelectionModifierCursorController != null) {
            observer.removeOnTouchModeChangeListener(mSelectionModifierCursorController);
        }
        }

        if (mError != null) {
            hideError();
@@ -4290,11 +4283,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener

        if (mPreDrawState == PREDRAW_DONE) {
            final ViewTreeObserver observer = getViewTreeObserver();
            if (observer != null) {
            observer.removeOnPreDrawListener(this);
            mPreDrawState = PREDRAW_NOT_REGISTERED;
        }
        }

        int color = mCurTextColor;

@@ -5541,8 +5532,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                    ellipsisWidth);
        } else {
            if (boring == UNKNOWN_BORING) {
                boring = BoringLayout.isBoring(mTransformed, mTextPaint,
                                               mBoring);
                boring = BoringLayout.isBoring(mTransformed, mTextPaint, mBoring);
                if (boring != null) {
                    mBoring = boring;
                }
@@ -8655,9 +8645,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        }
    }

    private class HandleView extends View {
    private class HandleView extends View implements ViewTreeObserver.OnScrollChangedListener {
        private Drawable mDrawable;
        private final PopupWindow mContainer;
        private final ScrollingPopupWindow mContainer;
        private int mPositionX;
        private int mPositionY;
        private final CursorController mController;
@@ -8726,7 +8716,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        public HandleView(CursorController controller, int pos) {
            super(TextView.this.mContext);
            mController = controller;
            mContainer = new PopupWindow(TextView.this.mContext, null,
            mContainer = new ScrollingPopupWindow(TextView.this.mContext, null,
                    com.android.internal.R.attr.textSelectHandleWindowStyle);
            mContainer.setSplitTouchEnabled(true);
            mContainer.setClippingEnabled(false);
@@ -8794,24 +8784,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                return;
            }
            mContainer.setContentView(this);
            final int[] coords = mTempCoords;
            TextView.this.getLocationInWindow(coords);
            mContainerPositionX = coords[0] + mPositionX;
            mContainerPositionY = coords[1] + mPositionY;
            mContainer.showAtLocation(TextView.this, 0, mContainerPositionX, mContainerPositionY);
            mContainerPositionX = mPositionX;
            mContainerPositionY = mPositionY - TextView.this.getHeight();
            mContainer.showAsDropDown(TextView.this, mContainerPositionX, mContainerPositionY);

            // Hide paste view when handle is moved on screen.
            if (mPastePopupWindow != null) {
                mPastePopupWindow.hide();
            }
            hidePastePopupWindow();
        }

        public void hide() {
            mIsDragging = false;
            mContainer.dismiss();
            if (mPastePopupWindow != null) {
                mPastePopupWindow.hide();
            }
            hidePastePopupWindow();
        }

        public boolean isShowing() {
@@ -8834,19 +8818,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            final int compoundPaddingRight = getCompoundPaddingRight();

            final TextView hostView = TextView.this;
            final int left = 0;
            final int right = hostView.getWidth();
            final int top = 0;
            final int bottom = hostView.getHeight();

            if (mTempRect == null) {
                mTempRect = new Rect();
            }
            final Rect clip = mTempRect;
            clip.left = left + compoundPaddingLeft;
            clip.top = top + extendedPaddingTop;
            clip.right = right - compoundPaddingRight;
            clip.bottom = bottom - extendedPaddingBottom;
            clip.left = compoundPaddingLeft;
            clip.top = extendedPaddingTop;
            clip.right = hostView.getWidth() - compoundPaddingRight;
            clip.bottom = hostView.getHeight() - extendedPaddingBottom;

            final ViewParent parent = hostView.getParent();
            if (parent == null || !parent.getChildVisibleRect(hostView, clip, null)) {
@@ -8858,7 +8838,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            final int posX = coords[0] + mPositionX + (int) mHotspotX;
            final int posY = coords[1] + mPositionY + (int) mHotspotY;

            return posX >= clip.left && posX <= clip.right &&
            // Offset by 1 to take into account 0.5 and int rounding around getPrimaryHorizontal.
            return posX >= clip.left - 1 && posX <= clip.right + 1 &&
                    posY >= clip.top && posY <= clip.bottom;
        }

@@ -8868,23 +8849,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            if (isPositionVisible()) {
                int[] coords = null;
                if (mContainer.isShowing()) {
                    coords = mTempCoords;
                    TextView.this.getLocationInWindow(coords);
                    final int containerPositionX = coords[0] + mPositionX;
                    final int containerPositionY = coords[1] + mPositionY;
                    final int containerPositionX = mPositionX;
                    final int containerPositionY = mPositionY - TextView.this.getHeight();

                    if (containerPositionX != mContainerPositionX || 
                        containerPositionY != mContainerPositionY) {
                        mContainerPositionX = containerPositionX;
                        mContainerPositionY = containerPositionY;

                        mContainer.update(mContainerPositionX, mContainerPositionY,
                        mContainer.update(TextView.this, mContainerPositionX, mContainerPositionY,
                                mRight - mLeft, mBottom - mTop);

                        // Hide paste popup window as soon as a scroll occurs.
                        if (mPastePopupWindow != null) {
                            mPastePopupWindow.hide();
                        }
                        hidePastePopupWindow();
                    }
                } else {
                    show();
@@ -8902,9 +8879,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                        mLastParentY = coords[1];
                    }
                    // Hide paste popup window as soon as the handle is dragged.
                    if (mPastePopupWindow != null) {
                        mPastePopupWindow.hide();
                    }
                    hidePastePopupWindow();
                }
            } else {
                hide();
@@ -9008,10 +8983,60 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                mPastePopupWindow.show();
            }
        }

        void hidePastePopupWindow() {
            if (mPastePopupWindow != null) {
                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 {
        private static final int DELAY_BEFORE_FADE_OUT = 4100;
        private static final int DELAY_BEFORE_FADE_OUT = 4000;
        private static final int DELAY_BEFORE_PASTE = 2000;
        private static final int RECENT_CUT_COPY_DURATION = 15 * 1000;

@@ -9027,7 +9052,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        public void show(int delayBeforePaste) {
            updatePosition();
            hideDelayed();
            getHandle().show();
            removePastePopupCallback();
            final long durationSinceCutOrCopy = SystemClock.uptimeMillis() - sLastCutOrCopyTime;
            if (durationSinceCutOrCopy < RECENT_CUT_COPY_DURATION) {
@@ -9547,10 +9571,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            mInsertionPointCursorController = new InsertionPointCursorController();

            final ViewTreeObserver observer = getViewTreeObserver();
            if (observer != null) {
            observer.addOnTouchModeChangeListener(mInsertionPointCursorController);
        }
        }

        return mInsertionPointCursorController;
    }
@@ -9564,10 +9586,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            mSelectionModifierCursorController = new SelectionModifierCursorController();

            final ViewTreeObserver observer = getViewTreeObserver();
            if (observer != null) {
            observer.addOnTouchModeChangeListener(mSelectionModifierCursorController);
        }
        }

        return mSelectionModifierCursorController;
    }