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

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

Merge "resolved conflicts for merge of ba04dbc6 to master"

parents e7aa0785 cf1e925a
Loading
Loading
Loading
Loading
+80 −52
Original line number Diff line number Diff line
@@ -4364,6 +4364,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener

        switch (keyCode) {
            case KeyEvent.KEYCODE_ENTER:
                mEnterKeyIsDown = true;
                // If ALT modifier is held, then we always insert a
                // newline character.
                if ((event.getMetaState()&KeyEvent.META_ALT_ON) == 0) {
@@ -4396,6 +4397,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                break;
                
            case KeyEvent.KEYCODE_DPAD_CENTER:
                mDPadCenterIsDown = true;
                if (shouldAdvanceFocusOnEnter()) {
                    return 0;
                }
@@ -4490,6 +4492,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener

        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_CENTER:
                mDPadCenterIsDown = false;
                /*
                 * If there is a click listener, just call through to
                 * super, which will invoke it.
@@ -4510,6 +4513,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                return super.onKeyUp(keyCode, event);
                
            case KeyEvent.KEYCODE_ENTER:
                mEnterKeyIsDown = false;
                if (mInputContentType != null
                        && mInputContentType.onEditorActionListener != null
                        && mInputContentType.enterDown) {
@@ -7288,9 +7292,21 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        }

        // Two ints packed in a long
        return packRangeInLong(start, end);
    }

    private static long packRangeInLong(int start, int end) {
        return (((long) start) << 32) | end;
    }

    private static int extractRangeStartFromLong(long range) {
        return (int) (range >>> 32);
    }

    private static int extractRangeEndFromLong(long range) {
        return (int) (range & 0x00000000FFFFFFFFL);
    }
    
    private void selectCurrentWord() {
        // In case selection mode is started after an orientation change or after a select all,
        // use the current selection instead of creating one
@@ -7298,67 +7314,31 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            return;
        }

        int selectionStart, selectionEnd;
        int minOffset, maxOffset;

        if (mDPadCenterIsDown || mEnterKeyIsDown) {
            minOffset = getSelectionStart();
            maxOffset = getSelectionEnd();
        } else {
            // selectionModifierCursorController is not null at that point
            SelectionModifierCursorController selectionModifierCursorController =
                ((SelectionModifierCursorController) mSelectionModifierCursorController);
        int minOffset = selectionModifierCursorController.getMinTouchOffset();
        int maxOffset = selectionModifierCursorController.getMaxTouchOffset();

        if (minOffset == maxOffset) {
            int offset = Math.max(0, Math.min(minOffset, mTransformed.length()));

            // Tolerance, number of charaters around tapped position
            final int range = 1;
            final int max = mTransformed.length() - 1;

            // 'Smart' word selection: detect position between words
            for (int i = -range; i <= range; i++) {
                int index = offset + i;
                if (index >= 0 && index <= max) {
                    if (Character.isSpaceChar(mTransformed.charAt(index))) {
                        // Select current space
                        selectionStart = index;
                        selectionEnd = selectionStart + 1;

                        // Extend selection to maximum space range
                        while (selectionStart > 0 &&
                                Character.isSpaceChar(mTransformed.charAt(selectionStart - 1))) {
                            selectionStart--;
                        }
                        while (selectionEnd < max &&
                                Character.isSpaceChar(mTransformed.charAt(selectionEnd))) {
                            selectionEnd++;
                        }

                        Selection.setSelection((Spannable) mText, selectionStart, selectionEnd);
                        return;
                    }
                }
            minOffset = selectionModifierCursorController.getMinTouchOffset();
            maxOffset = selectionModifierCursorController.getMaxTouchOffset();
        }

            // 'Smart' word selection: detect position at beginning or end of text.
            if (offset <= range) {
                Selection.setSelection((Spannable) mText, 0, 0);
                return;
            }
            if (offset >= (max - range)) {
                Selection.setSelection((Spannable) mText, max + 1, max + 1);
                return;
            }
        }
        int selectionStart, selectionEnd;

        long wordLimits = getWordLimitsAt(minOffset);
        if (wordLimits >= 0) {
            selectionStart = (int) (wordLimits >>> 32);
            selectionStart = extractRangeStartFromLong(wordLimits);
        } else {
            selectionStart = Math.max(minOffset - 5, 0);
        }

        wordLimits = getWordLimitsAt(maxOffset);
        if (wordLimits >= 0) {
            selectionEnd = (int) (wordLimits & 0x00000000FFFFFFFFL);
            selectionEnd = extractRangeEndFromLong(wordLimits);
        } else {
            selectionEnd = Math.min(maxOffset + 5, mText.length());
        }
@@ -7487,7 +7467,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener

        switch (id) {
            case ID_COPY_URL:

                URLSpan[] urls = ((Spanned) mText).getSpans(min, max, URLSpan.class);
                if (urls.length >= 1) {
                    ClipData clip = null;
@@ -7513,6 +7492,49 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        return false;
    }

    /**
     * Prepare text so that there are not zero or two spaces at beginning and end of region defined
     * by [min, max] when replacing this region by paste.
     */
    private long prepareSpacesAroundPaste(int min, int max, CharSequence paste) {
        // Paste adds/removes spaces before or after insertion as needed.
        if (Character.isSpaceChar(paste.charAt(0))) {
            if (min > 0 && Character.isSpaceChar(mTransformed.charAt(min - 1))) {
                // Two spaces at beginning of paste: remove one
                final int originalLength = mText.length();
                ((Editable) mText).replace(min - 1, min, "");
                // Due to filters, there is no garantee that exactly one character was
                // removed. Count instead.
                final int delta = mText.length() - originalLength;
                min += delta;
                max += delta;
            }
        } else {
            if (min > 0 && !Character.isSpaceChar(mTransformed.charAt(min - 1))) {
                // No space at beginning of paste: add one
                final int originalLength = mText.length();
                ((Editable) mText).replace(min, min, " ");
                // Taking possible filters into account as above.
                final int delta = mText.length() - originalLength;
                min += delta;
                max += delta;
            }
        }

        if (Character.isSpaceChar(paste.charAt(paste.length() - 1))) {
            if (max < mText.length() && Character.isSpaceChar(mTransformed.charAt(max))) {
                // Two spaces at end of paste: remove one
                ((Editable) mText).replace(max, max + 1, "");
            }
        } else {
            if (max < mText.length() && !Character.isSpaceChar(mTransformed.charAt(max))) {
                // No space at end of paste: add one
                ((Editable) mText).replace(max, max, " ");
            }
        }
        return packRangeInLong(min, max);
    }

    @Override
    public boolean performLongClick() {
        if (super.performLongClick()) {
@@ -7704,6 +7726,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                            CharSequence paste = clip.getItem(i).coerceToText(getContext());
                            if (paste != null) {
                                if (!didfirst) {
                                    long minMax = prepareSpacesAroundPaste(min, max, paste);
                                    min = extractRangeStartFromLong(minMax);
                                    max = extractRangeEndFromLong(minMax);
                                    Selection.setSelection((Spannable) mText, max);
                                    ((Editable) mText).replace(min, max, paste);
                                } else {
@@ -7714,7 +7739,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                        }
                        stopSelectionActionMode();
                    }

                    return true;

                case ID_CUT:
@@ -8329,6 +8353,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    private CursorController        mSelectionModifierCursorController;
    private ActionMode              mSelectionActionMode;
    private int                     mLastTouchOffset = -1;
    // These are needed to desambiguate a long click. If the long click comes from ones of these, we
    // select from the current cursor position. Otherwise, select from long pressed position.
    private boolean                 mDPadCenterIsDown = false;
    private boolean                 mEnterKeyIsDown = false;
    // Created once and shared by different CursorController helper methods.
    // Only one cursor controller is active at any time which prevent race conditions.
    private static Rect             sCursorControllerTempRect = new Rect();