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

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

Merge "Text handles movement improvements."

parents d90ce9b4 ddf00b8a
Loading
Loading
Loading
Loading
+30 −35
Original line number Diff line number Diff line
@@ -8655,9 +8655,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        private float mTouchToWindowOffsetX;
        private float mTouchToWindowOffsetY;
        private float mHotspotX;
        private float mHotspotY;
        private int mHeight;
        // 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;
        private float mDownPositionX, mDownPositionY;
@@ -8767,7 +8769,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            final int handleHeight = mDrawable.getIntrinsicHeight();

            mTouchOffsetY = -handleHeight * 0.3f;
            mHotspotY = 0;
            mIdealVerticalOffset = 0.7f * handleHeight;
            mHeight = handleHeight;
            invalidate();
        }
@@ -8836,7 +8838,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            final int[] coords = mTempCoords;
            hostView.getLocationInWindow(coords);
            final int posX = coords[0] + mPositionX + (int) mHotspotX;
            final int posY = coords[1] + mPositionY + (int) mHotspotY;
            final int posY = coords[1] + mPositionY;

            // Offset by 1 to take into account 0.5 and int rounding around getPrimaryHorizontal.
            return posX >= clip.left - 1 && posX <= clip.right + 1 &&
@@ -8901,6 +8903,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                    mDownPositionY = ev.getRawY();
                    mTouchToWindowOffsetX = mDownPositionX - mPositionX;
                    mTouchToWindowOffsetY = mDownPositionY - mPositionY;

                    final int[] coords = mTempCoords;
                    TextView.this.getLocationInWindow(coords);
                    mLastParentX = coords[0];
@@ -8915,8 +8918,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                case MotionEvent.ACTION_MOVE: {
                    final float rawX = ev.getRawX();
                    final float rawY = ev.getRawY();

                    // Vertical hysteresis: vertical down movement tends to snap to ideal offset
                    final float previousVerticalOffset = mTouchToWindowOffsetY - mLastParentY;
                    final float currentVerticalOffset = rawY - mPositionY - mLastParentY;
                    float newVerticalOffset;
                    if (previousVerticalOffset < mIdealVerticalOffset) {
                        newVerticalOffset = Math.min(currentVerticalOffset, mIdealVerticalOffset);
                        newVerticalOffset = Math.max(newVerticalOffset, previousVerticalOffset);
                    } else {
                        newVerticalOffset = Math.max(currentVerticalOffset, mIdealVerticalOffset);
                        newVerticalOffset = Math.min(newVerticalOffset, previousVerticalOffset);
                    }
                    mTouchToWindowOffsetY = newVerticalOffset + mLastParentY;

                    final float newPosX = rawX - mTouchToWindowOffsetX + mHotspotX;
                    final float newPosY = rawY - mTouchToWindowOffsetY + mHotspotY + mTouchOffsetY;
                    final float newPosY = rawY - mTouchToWindowOffsetY + mTouchOffsetY;

                    mController.updatePosition(this, Math.round(newPosX), Math.round(newPosY));
                    break;
@@ -8954,18 +8971,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            return mIsDragging;
        }

        void positionAtCursor(final int offset, boolean bottom) {
        void positionAtCursor(final int offset) {
            addPositionToTouchUpFilter(offset);
            final int width = mDrawable.getIntrinsicWidth();
            final int height = mDrawable.getIntrinsicHeight();
            final int line = mLayout.getLineForOffset(offset);
            final int lineTop = mLayout.getLineTop(line);
            final int lineBottom = mLayout.getLineBottom(line);

            final Rect bounds = sCursorControllerTempRect;
            bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX) +
                    TextView.this.mScrollX;
            bounds.top = (bottom ? lineBottom : lineTop - mHeight) + TextView.this.mScrollY;
            bounds.top = lineBottom + TextView.this.mScrollY;

            bounds.right = bounds.left + width;
            bounds.bottom = bounds.top + height;
@@ -9107,10 +9123,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener

        public void updatePosition(HandleView handle, int x, int y) {
            final int previousOffset = getSelectionStart();
            int offset = getHysteresisOffset(x, y, previousOffset);
            final int newOffset = getOffset(x, y);

            if (offset != previousOffset) {
                updateOffset(handle, offset);
            if (newOffset != previousOffset) {
                updateOffset(handle, newOffset);
                removePastePopupCallback();
            }
            hideDelayed();
@@ -9131,7 +9147,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                return;
            }

            getHandle().positionAtCursor(offset, true);
            getHandle().positionAtCursor(offset);
        }

        public int getCurrentOffset(HandleView handle) {
@@ -9215,8 +9231,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            int selectionStart = getSelectionStart();
            int selectionEnd = getSelectionEnd();

            final int previousOffset = handle == mStartHandle ? selectionStart : selectionEnd;
            int offset = getHysteresisOffset(x, y, previousOffset);
            int offset = getOffset(x, y);

            // Handle the case where start and end are swapped, making sure start <= end
            if (handle == mStartHandle) {
@@ -9275,8 +9290,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            }

            // The handles have been created since the controller isShowing().
            mStartHandle.positionAtCursor(selectionStart, true);
            mEndHandle.positionAtCursor(selectionEnd, true);
            mStartHandle.positionAtCursor(selectionStart);
            mEndHandle.positionAtCursor(selectionEnd);
        }

        public int getCurrentOffset(HandleView handle) {
@@ -9406,26 +9421,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        return offset;
    }

    int getHysteresisOffset(int x, int y, int previousOffset) {
        final Layout layout = getLayout();
        if (layout == null) return -1;

        int line = getLineAtCoordinate(y);
        final int previousLine = layout.getLineForOffset(previousOffset);
        final int previousLineTop = layout.getLineTop(previousLine);
        final int previousLineBottom = layout.getLineBottom(previousLine);
        final int hysteresisThreshold = (previousLineBottom - previousLineTop) / 8;

        // If new line is just before or after previous line and y position is less than
        // hysteresisThreshold away from previous line, keep cursor on previous line.
        if (((line == previousLine + 1) && ((y - previousLineBottom) < hysteresisThreshold)) ||
            ((line == previousLine - 1) && ((previousLineTop - y)    < hysteresisThreshold))) {
            line = previousLine;
        }

        return getOffsetAtCoordinate(line, x);
    }

    private int convertToLocalHorizontalCoordinate(int x) {
        x -= getTotalPaddingLeft();
        // Clamp the position to inside of the view.