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

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

Merge "Added a touch up filter in text selection handles." into honeycomb

parents b2601359 aa8d73bf
Loading
Loading
Loading
Loading
+79 −17
Original line number Diff line number Diff line
@@ -7931,9 +7931,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            max = Math.max(0, Math.max(selStart, selEnd));
        }

        ClipboardManager clipboard = (ClipboardManager)getContext()
                .getSystemService(Context.CLIPBOARD_SERVICE);

        switch (id) {
            case ID_COPY_URL:
                URLSpan[] urls = ((Spanned) mText).getSpans(min, max, URLSpan.class);
@@ -8402,8 +8399,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
         */
        public void updatePosition(HandleView handle, int x, int y);

        public void updateOffset(HandleView handle, int offset);

        public void updatePosition();

        public int getCurrentOffset(HandleView handle);

        /**
         * This method is called by {@link #onTouchEvent(MotionEvent)} and gives the controller
         * a chance to become active and/or visible.
@@ -8420,7 +8421,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    }

    private class PastePopupMenu implements OnClickListener {
        private PopupWindow mContainer;
        private final PopupWindow mContainer;
        private int mPositionX;
        private int mPositionY;
        private View mPasteView, mNoPasteView;
@@ -8519,12 +8520,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    }

    private class HandleView extends View {
        private boolean mPositionOnTop = false;
        private Drawable mDrawable;
        private PopupWindow mContainer;
        private final PopupWindow mContainer;
        private int mPositionX;
        private int mPositionY;
        private CursorController mController;
        private final CursorController mController;
        private boolean mIsDragging;
        private float mTouchToWindowOffsetX;
        private float mTouchToWindowOffsetY;
@@ -8541,6 +8541,46 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        private PastePopupMenu mPastePopupWindow;
        private Runnable mLongPressCallback;

        // Touch-up filter: number of previous positions remembered
        private static final int HISTORY_SIZE = 5;
        private static final int TOUCH_UP_FILTER_DELAY = 150;
        private final long[] mPreviousOffsetsTimes = new long[HISTORY_SIZE];
        private final int[] mPreviousOffsets = new int[HISTORY_SIZE];
        private int mPreviousOffsetIndex = 0;
        private int mNumberPreviousOffsets = 0;

        public void startTouchUpFilter(int offset) {
            mNumberPreviousOffsets = 0;
            addPositionToTouchUpFilter(offset);
        }

        public void addPositionToTouchUpFilter(int offset) {
            if (mNumberPreviousOffsets > 0 &&
                    mPreviousOffsets[mPreviousOffsetIndex] == offset) {
                // Make sure only actual changes of position are recorded.
                return;
            }

            mPreviousOffsetIndex = (mPreviousOffsetIndex + 1) % HISTORY_SIZE;
            mPreviousOffsets[mPreviousOffsetIndex] = offset;
            mPreviousOffsetsTimes[mPreviousOffsetIndex] = SystemClock.uptimeMillis();
            mNumberPreviousOffsets++;
        }

        public void filterOnTouchUp() {
            final long now = SystemClock.uptimeMillis();
            int i = 0;
            int index = 0;
            final int iMax = Math.min(mNumberPreviousOffsets, HISTORY_SIZE);
            while (i < iMax) {
                index = (mPreviousOffsetIndex - i + HISTORY_SIZE) % HISTORY_SIZE;
                if ((now - mPreviousOffsetsTimes[index]) >= TOUCH_UP_FILTER_DELAY) break;
                i++;
            }

            mController.updateOffset(this, mPreviousOffsets[index]);
        }

        public static final int LEFT = 0;
        public static final int CENTER = 1;
        public static final int RIGHT = 2;
@@ -8736,20 +8776,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        @Override
        protected void onDraw(Canvas c) {
            mDrawable.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
            if (mPositionOnTop) {
                c.save();
                c.rotate(180, (mRight - mLeft) / 2, (mBottom - mTop) / 2);
                mDrawable.draw(c);
                c.restore();
            } else {
            mDrawable.draw(c);
        }
        }

        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            switch (ev.getActionMasked()) {
            case MotionEvent.ACTION_DOWN: {
                startTouchUpFilter(mController.getCurrentOffset(this));
                mDownPositionX = ev.getRawX();
                mDownPositionY = ev.getRawY();
                mTouchToWindowOffsetX = mDownPositionX - mPositionX;
@@ -8806,6 +8840,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                        }
                    }
                }
                filterOnTouchUp();
                mIsDragging = false;
                break;

@@ -8823,6 +8858,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        }

        void positionAtCursor(final int offset, boolean bottom) {
            addPositionToTouchUpFilter(offset);
            final int width = mDrawable.getIntrinsicWidth();
            final int height = mDrawable.getIntrinsicHeight();
            final int line = mLayout.getLineForOffset(offset);
@@ -8938,12 +8974,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            int offset = getHysteresisOffset(x, y, previousOffset);

            if (offset != previousOffset) {
                Selection.setSelection((Spannable) mText, offset);
                updatePosition();
                updateOffset(handle, offset);
            }
            hideDelayed();
        }

        public void updateOffset(HandleView handle, int offset) {
            Selection.setSelection((Spannable) mText, offset);
            updatePosition();
        }

        public void updatePosition() {
            final int offset = getSelectionStart();

@@ -8957,6 +8997,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            getHandle().positionAtCursor(offset, true);
        }

        public int getCurrentOffset(HandleView handle) {
            return getSelectionStart();
        }

        public boolean onTouchEvent(MotionEvent ev) {
            return false;
        }
@@ -9067,6 +9111,20 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            updatePosition();
        }

        public void updateOffset(HandleView handle, int offset) {
            int start = getSelectionStart();
            int end = getSelectionEnd();

            if (mStartHandle == handle) {
                start = offset;
            } else {
                end = offset;
            }

            Selection.setSelection((Spannable) mText, start, end);
            updatePosition();
        }

        public void updatePosition() {
            if (!isShowing()) {
                return;
@@ -9087,6 +9145,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            mEndHandle.positionAtCursor(selectionEnd, true);
        }

        public int getCurrentOffset(HandleView handle) {
            return mStartHandle == handle ? getSelectionStart() : getSelectionEnd();
        }

        public boolean onTouchEvent(MotionEvent event) {
            // This is done even when the View does not have focus, so that long presses can start
            // selection and tap can move cursor from this tap position.