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

Commit b9bbbb1d authored by Mady Mellor's avatar Mady Mellor
Browse files

Text selection - Don't select vertical white space

This alters text selection so that you won't select a
whitespace line above or below your selection unless you select
a non-whitespace character past the line.

Change-Id: Ic93f77f6ccecb06be2acc83524ca9e9a627660ce
parent bf54a8af
Loading
Loading
Loading
Loading
+60 −12
Original line number Diff line number Diff line
@@ -3331,7 +3331,7 @@ public class Editor {
        // Minimum touch target size for handles
        private int mMinSize;
        // Indicates the line of text that the handle is on.
        protected int mLine = -1;
        protected int mPrevLine = -1;

        public HandleView(Drawable drawableLtr, Drawable drawableRtl) {
            super(mTextView.getContext());
@@ -3509,7 +3509,7 @@ public class Editor {
                    addPositionToTouchUpFilter(offset);
                }
                final int line = layout.getLineForOffset(offset);
                mLine = line;
                mPrevLine = line;

                mPositionX = (int) (layout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX -
                        getHorizontalOffset() + getCursorOffset());
@@ -3858,19 +3858,22 @@ public class Editor {
        public void updatePosition(float x, float y) {
            final int trueOffset = mTextView.getOffsetForPosition(x, y);
            final int currLine = mTextView.getLineAtCoordinate(y);
            int offset = trueOffset;
            boolean positionCursor = false;

            // Don't select white space on different lines.
            if (isWhitespaceLine(mPrevLine, currLine, trueOffset)) return;

            boolean positionCursor = false;
            int offset = trueOffset;
            int end = getWordEnd(offset, true);
            int start = getWordStart(offset);

            if (offset < mPrevOffset) {
                // User is increasing the selection.
                if (!mInWord || currLine < mLine) {
                if (!mInWord || currLine < mPrevLine) {
                    // We're not in a word, or we're on a different line so we'll expand by
                    // word. First ensure the user has at least entered the next word.
                    int offsetToWord = Math.min((end - start) / 2, 2);
                    if (offset <= end - offsetToWord || currLine < mLine) {
                    if (offset <= end - offsetToWord || currLine < mPrevLine) {
                        offset = start;
                    } else {
                        offset = mPrevOffset;
@@ -3882,7 +3885,7 @@ public class Editor {
                positionCursor = true;
            } else if (offset - mTouchWordOffset > mPrevOffset) {
                // User is shrinking the selection.
                if (currLine > mLine) {
                if (currLine > mPrevLine) {
                    // We're on a different line, so we'll snap to word boundaries.
                    offset = end;
                }
@@ -3897,7 +3900,7 @@ public class Editor {
                final int selectionEnd = mTextView.getSelectionEnd();
                if (offset >= selectionEnd) {
                    // We can't cross the handles so let's just constrain the Y value.
                    int alteredOffset = mTextView.getOffsetAtCoordinate(mLine, x);
                    int alteredOffset = mTextView.getOffsetAtCoordinate(mPrevLine, x);
                    if (alteredOffset >= selectionEnd) {
                        // Can't pass the other drag handle.
                        offset = Math.max(0, selectionEnd - 1);
@@ -3962,6 +3965,10 @@ public class Editor {
        public void updatePosition(float x, float y) {
            final int trueOffset = mTextView.getOffsetForPosition(x, y);
            final int currLine = mTextView.getLineAtCoordinate(y);

            // Don't select white space on different lines.
            if (isWhitespaceLine(mPrevLine, currLine, trueOffset)) return;

            int offset = trueOffset;
            boolean positionCursor = false;

@@ -3970,11 +3977,11 @@ public class Editor {

            if (offset > mPrevOffset) {
                // User is increasing the selection.
                if (!mInWord || currLine > mLine) {
                if (!mInWord || currLine > mPrevLine) {
                    // We're not in a word, or we're on a different line so we'll expand by
                    // word. First ensure the user has at least entered the next word.
                    int midPoint = Math.min((end - start) / 2, 2);
                    if (offset >= start + midPoint || currLine > mLine) {
                    if (offset >= start + midPoint || currLine > mPrevLine) {
                        offset = end;
                    } else {
                        offset = mPrevOffset;
@@ -3986,7 +3993,7 @@ public class Editor {
                positionCursor = true;
            } else if (offset + mTouchWordOffset < mPrevOffset) {
                // User is shrinking the selection.
                if (currLine > mLine) {
                if (currLine > mPrevLine) {
                    // We're on a different line, so we'll snap to word boundaries.
                    offset = getWordStart(offset);
                }
@@ -4000,7 +4007,7 @@ public class Editor {
                final int selectionStart = mTextView.getSelectionStart();
                if (offset <= selectionStart) {
                    // We can't cross the handles so let's just constrain the Y value.
                    int alteredOffset = mTextView.getOffsetAtCoordinate(mLine, x);
                    int alteredOffset = mTextView.getOffsetAtCoordinate(mPrevLine, x);
                    int length = mTextView.getText().length();
                    if (alteredOffset <= selectionStart) {
                        // Can't pass the other drag handle.
@@ -4028,6 +4035,36 @@ public class Editor {
        }
    }

    /**
     * Checks whether selection is happening on a different line than previous and
     * if that line only contains whitespace up to the touch location.
     *
     * @param prevLine The previous line the selection was on.
     * @param currLine The current line being selected.
     * @param offset The offset in the text where the touch occurred.
     * @return Whether or not it was just a white space line being selected.
     */
    private boolean isWhitespaceLine(int prevLine, int currLine, int offset) {
        if (prevLine == currLine) {
            // Same line; don't care.
            return false;
        }
        CharSequence text = mTextView.getText();
        if (offset == text.length()) {
            // No character at the last position.
            return false;
        }
        int lineEndOffset = mTextView.getLayout().getLineEnd(currLine);
        for (int cp, i = offset; i < lineEndOffset; i += Character.charCount(cp)) {
            cp = Character.codePointAt(text, i);
            if (!Character.isSpaceChar(cp) && !Character.isWhitespace(cp)) {
                // There are non white space chars on the line.
                return false;
            }
        }
        return true;
    }

    /**
     * A CursorController instance can be used to control a cursor in the text.
     */
@@ -4112,6 +4149,8 @@ public class Editor {
        private int mStartOffset = -1;
        // Indicates whether the user is selecting text and using the drag accelerator.
        private boolean mDragAcceleratorActive;
        // Indicates the line of text the drag accelerator is on.
        private int mPrevLine = -1;

        SelectionModifierCursorController() {
            resetTouchOffsets();
@@ -4209,6 +4248,8 @@ public class Editor {
                        }
                    }

                    // New selection, reset line.
                    mPrevLine = mTextView.getLineAtCoordinate(y);
                    mDownPositionX = x;
                    mDownPositionY = y;
                    mGestureStayedInTapRegion = true;
@@ -4265,6 +4306,13 @@ public class Editor {
                            if (my > fingerOffset) my -= fingerOffset;
                            offset = mTextView.getOffsetForPosition(mx, my);

                            int currLine = mTextView.getLineAtCoordinate(my);

                            // Don't select white space on different lines.
                            if (isWhitespaceLine(mPrevLine, currLine, offset)) return;

                            mPrevLine = currLine;

                            // Perform the check for closeness at edge of view, if we're very close
                            // don't adjust the offset to be in front of the finger - otherwise the
                            // user can't select words at the edge.