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

Commit 0138e4c7 authored by Keisuke Kuroyanagi's avatar Keisuke Kuroyanagi Committed by Mady Mellor
Browse files

Track difference between touch and word in x coordinate.

After a handle is snapped to the word, the difference was
tracked in offset. It can break grapheme clusters, ignores
character width, and makes it difficult to select text near
line breaks.

Bug: 21005599
Change-Id: I42402a377670c7e3c6d6e6583744d085ae52bba2
parent 21623faa
Loading
Loading
Loading
Loading
+62 −26
Original line number Diff line number Diff line
@@ -3855,8 +3855,8 @@ public class Editor {
    private class SelectionStartHandleView extends HandleView {
        // Indicates whether the cursor is making adjustments within a word.
        private boolean mInWord = false;
        // Offset to track difference between touch and word boundary.
        protected int mTouchWordOffset;
        // Difference between touch position and word boundary position.
        private float mTouchWordDelta;

        public SelectionStartHandleView(Drawable drawableLtr, Drawable drawableRtl) {
            super(drawableLtr, drawableRtl);
@@ -3908,19 +3908,37 @@ public class Editor {
                        offset = mPreviousOffset;
                    }
                }
                mTouchWordOffset = Math.max(trueOffset - offset, 0);
                final Layout layout = mTextView.getLayout();
                if (layout != null && offset < trueOffset) {
                    final float adjustedX = layout.getPrimaryHorizontal(offset);
                    mTouchWordDelta =
                            mTextView.convertToLocalHorizontalCoordinate(x) - adjustedX;
                } else {
                    mTouchWordDelta = 0.0f;
                }
                positionCursor = true;
            } else if (offset - mTouchWordOffset > mPreviousOffset || currLine > mPrevLine) {
            } else {
                final int adjustedOffset =
                        mTextView.getOffsetAtCoordinate(currLine, x - mTouchWordDelta);
                if (adjustedOffset > mPreviousOffset || currLine > mPrevLine) {
                    // User is shrinking the selection.
                    if (currLine > mPrevLine) {
                        // We're on a different line, so we'll snap to word boundaries.
                        offset = start;
                    mTouchWordOffset = Math.max(trueOffset - offset, 0);
                        final Layout layout = mTextView.getLayout();
                        if (layout != null && offset < trueOffset) {
                            final float adjustedX = layout.getPrimaryHorizontal(offset);
                            mTouchWordDelta =
                                    mTextView.convertToLocalHorizontalCoordinate(x) - adjustedX;
                        } else {
                            mTouchWordDelta = 0.0f;
                        }
                    } else {
                    offset -= mTouchWordOffset;
                        offset = adjustedOffset;
                    }
                    positionCursor = true;
                }
            }

            // Handles can not cross and selection is at least one character.
            if (positionCursor) {
@@ -3934,7 +3952,7 @@ public class Editor {
                    } else {
                        offset = alteredOffset;
                    }
                    mTouchWordOffset = 0;
                    mTouchWordDelta = 0.0f;
                }
                mInWord = !getWordIteratorWithText().isBoundary(offset);
                positionAtCursorOffset(offset, false);
@@ -3946,7 +3964,7 @@ public class Editor {
            boolean superResult = super.onTouchEvent(event);
            if (event.getActionMasked() == MotionEvent.ACTION_UP) {
                // Reset the touch word offset when the user has lifted their finger.
                mTouchWordOffset = 0;
                mTouchWordDelta = 0.0f;
            }
            return superResult;
        }
@@ -3955,8 +3973,8 @@ public class Editor {
    private class SelectionEndHandleView extends HandleView {
        // Indicates whether the cursor is making adjustments within a word.
        private boolean mInWord = false;
        // Offset to track difference between touch and word boundary.
        protected int mTouchWordOffset;
        // Difference between touch position and word boundary position.
        private float mTouchWordDelta;

        public SelectionEndHandleView(Drawable drawableLtr, Drawable drawableRtl) {
            super(drawableLtr, drawableRtl);
@@ -4008,19 +4026,37 @@ public class Editor {
                        offset = mPreviousOffset;
                    }
                }
                mTouchWordOffset = Math.max(offset - trueOffset, 0);
                final Layout layout = mTextView.getLayout();
                if (layout != null && offset > trueOffset) {
                    final float adjustedX = layout.getPrimaryHorizontal(offset);
                    mTouchWordDelta =
                            adjustedX - mTextView.convertToLocalHorizontalCoordinate(x);
                } else {
                    mTouchWordDelta = 0.0f;
                }
                positionCursor = true;
            } else if (offset + mTouchWordOffset < mPreviousOffset || currLine < mPrevLine) {
            } else {
                final int adjustedOffset =
                        mTextView.getOffsetAtCoordinate(currLine, x + mTouchWordDelta);
                if (adjustedOffset < mPreviousOffset || currLine < mPrevLine) {
                    // User is shrinking the selection.
                    if (currLine < mPrevLine) {
                        // We're on a different line, so we'll snap to word boundaries.
                        offset = end;
                    mTouchWordOffset = Math.max(offset - trueOffset, 0);
                        final Layout layout = mTextView.getLayout();
                        if (layout != null && offset > trueOffset) {
                            final float adjustedX = layout.getPrimaryHorizontal(offset);
                            mTouchWordDelta =
                                    adjustedX - mTextView.convertToLocalHorizontalCoordinate(x);
                        } else {
                            mTouchWordDelta = 0.0f;
                        }
                    } else {
                    offset += mTouchWordOffset;
                        offset = adjustedOffset;
                    }
                    positionCursor = true;
                }
            }

            if (positionCursor) {
                final int selectionStart = mTextView.getSelectionStart();
@@ -4034,7 +4070,7 @@ public class Editor {
                    } else {
                        offset = Math.min(alteredOffset, length);
                    }
                    mTouchWordOffset = 0;
                    mTouchWordDelta = 0.0f;
                }
                mInWord = !getWordIteratorWithText().isBoundary(offset);
                positionAtCursorOffset(offset, false);
@@ -4046,7 +4082,7 @@ public class Editor {
            boolean superResult = super.onTouchEvent(event);
            if (event.getActionMasked() == MotionEvent.ACTION_UP) {
                // Reset the touch word offset when the user has lifted their finger.
                mTouchWordOffset = 0;
                mTouchWordDelta = 0.0f;
            }
            return superResult;
        }