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

Commit fae270c1 authored by Andrei Stingaceanu's avatar Andrei Stingaceanu
Browse files

Editor: enable double tap for selection after cut/copy.

* detect double tap in the TextView and pass it to Editor.
* add a timer (with getDoubleTapTimeout) for executing the
  single tap job in Editor.
* if double tap is detected then cancel the single tap job.

This way one tap shows the toolbar if within the timeframe
and two taps select the word and show the toolbar.

Bug: 20442587
Change-Id: I0a117939c896fcb13669346e30c9c48d319576dd
parent a0f6b87b
Loading
Loading
Loading
Loading
+31 −8
Original line number Diff line number Diff line
@@ -209,6 +209,10 @@ public class Editor {
    // Set when this TextView gained focus with some text selected. Will start selection mode.
    boolean mCreatedWithASelection;

    boolean mDoubleTap = false;

    private Runnable mSelectionModeWithoutSelectionRunnable;

    // The span controller helps monitoring the changes to which the Editor needs to react:
    // - EasyEditSpans, for which we have some UI to display on attach and on hide
    // - SelectionSpans, for which we need to call updateSelection if an IME is attached
@@ -349,6 +353,11 @@ public class Editor {
            mTextView.removeCallbacks(mShowSuggestionRunnable);
        }

        // Cancel the single tap delayed runnable.
        if (mSelectionModeWithoutSelectionRunnable != null) {
            mTextView.removeCallbacks(mSelectionModeWithoutSelectionRunnable);
        }

        destroyDisplayListsData();

        if (mSpellChecker != null) {
@@ -3722,11 +3731,29 @@ public class Editor {
        public void show() {
            super.show();

            final long durationSinceLastCutCopyOrTextChanged =
            final long durationSinceCutOrCopy =
                    SystemClock.uptimeMillis() - TextView.sLastCutCopyOrTextChangedTime;
            if (durationSinceLastCutCopyOrTextChanged < RECENT_CUT_COPY_DURATION) {

            // Cancel the single tap delayed runnable.
            if (mDoubleTap && mSelectionModeWithoutSelectionRunnable != null) {
                mTextView.removeCallbacks(mSelectionModeWithoutSelectionRunnable);
            }

            // Prepare and schedule the single tap runnable to run exactly after the double tap
            // timeout has passed.
            if (!mDoubleTap && (durationSinceCutOrCopy < RECENT_CUT_COPY_DURATION)) {
                if (mSelectionModeWithoutSelectionRunnable == null) {
                    mSelectionModeWithoutSelectionRunnable = new Runnable() {
                        public void run() {
                            startSelectionActionModeWithoutSelection();
                        }
                    };
                }

                mTextView.postDelayed(
                        mSelectionModeWithoutSelectionRunnable,
                        ViewConfiguration.getDoubleTapTimeout() + 1);
            }

            hideAfterDelay();
        }
@@ -4159,8 +4186,6 @@ public class Editor {
        // The offsets of that last touch down event. Remembered to start selection there.
        private int mMinTouchOffset, mMaxTouchOffset;

        // Double tap detection
        private long mPreviousTapUpTime = 0;
        private float mDownPositionX, mDownPositionY;
        private boolean mGestureStayedInTapRegion;

@@ -4242,8 +4267,7 @@ public class Editor {

                    // Double tap detection
                    if (mGestureStayedInTapRegion) {
                        long duration = SystemClock.uptimeMillis() - mPreviousTapUpTime;
                        if (duration <= ViewConfiguration.getDoubleTapTimeout()) {
                        if (mDoubleTap) {
                            final float deltaX = x - mDownPositionX;
                            final float deltaY = y - mDownPositionY;
                            final float distanceSquared = deltaX * deltaX + deltaY * deltaY;
@@ -4352,7 +4376,6 @@ public class Editor {
                    break;

                case MotionEvent.ACTION_UP:
                    mPreviousTapUpTime = SystemClock.uptimeMillis();
                    if (mDragAcceleratorActive) {
                        // No longer dragging to select text, let the parent intercept events.
                        mTextView.getParent().requestDisallowInterceptTouchEvent(false);
+19 −0
Original line number Diff line number Diff line
@@ -599,6 +599,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    private final Paint mHighlightPaint;
    private boolean mHighlightPathBogus = true;

    private boolean mFirstTouch = false;
    private long mLastTouchUpTime = 0;

    // Although these fields are specific to editable text, they are not added to Editor because
    // they are defined by the TextView's style and are theme-dependent.
    int mCursorDrawableRes;
@@ -8279,6 +8282,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    public boolean onTouchEvent(MotionEvent event) {
        final int action = event.getActionMasked();

        if (mEditor != null && action == MotionEvent.ACTION_DOWN) {
            // Detect double tap and inform the Editor.
            if (mFirstTouch && (SystemClock.uptimeMillis() - mLastTouchUpTime) <=
                    ViewConfiguration.getDoubleTapTimeout()) {
                mEditor.mDoubleTap = true;
                mFirstTouch = false;
            } else {
                mEditor.mDoubleTap = false;
                mFirstTouch = true;
            }
        }

        if (action == MotionEvent.ACTION_UP) {
            mLastTouchUpTime = SystemClock.uptimeMillis();
        }

        if (mEditor != null) {
            mEditor.onTouchEvent(event);