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

Commit dfac4435 authored by Clara Bayarri's avatar Clara Bayarri
Browse files

Fix Floating tool bar covers text during long press + drag

The existing implementation started the ActionMode even when knowing
a drag would start. Moved this logic to once the drag is complete,
to avoid the toolbar popping up while the user is still dragging.

Since the existing method selected the initial word when no other
selection existed, refactored that logic so it is also performed at
the start of the drag. Otherwise, the user sees no selection until
he drags over 2 or more words.

Bug: 21144634

Change-Id: I97cf89b1c4c3ebdbbd1af50bd1ce5aa4af72164b
parent f3edbb55
Loading
Loading
Loading
Loading
+43 −28
Original line number Diff line number Diff line
@@ -1004,14 +1004,14 @@ public class Editor {
                stopSelectionActionMode();
            } else {
                stopSelectionActionMode();
                startSelectionActionModeWithSelectionAndStartDrag();
                selectCurrentWordAndStartDrag();
            }
            handled = true;
        }

        // Start a new selection
        if (!handled) {
            handled = startSelectionActionModeWithSelectionAndStartDrag();
            handled = selectCurrentWordAndStartDrag();
        }

        return handled;
@@ -1723,23 +1723,10 @@ public class Editor {
        return mSelectionActionMode != null;
    }

    /**
     * Starts a Selection Action Mode with the current selection and enters drag mode. This should
     * be used whenever the mode is started from a touch event.
     *
     * @return true if the selection mode was actually started.
     */
    private boolean startSelectionActionModeWithSelectionAndStartDrag() {
        boolean selectionStarted = startSelectionActionModeWithSelectionInternal();
        if (selectionStarted) {
            getSelectionController().enterDrag();
        }
        return selectionStarted;
    }

    /**
     * Starts a Selection Action Mode with the current selection and ensures the selection handles
     * are shown. This should be used when the mode is started from a non-touch event.
     * are shown if there is a selection, otherwise the insertion handle is shown. This should be
     * used when the mode is started from a non-touch event.
     *
     * @return true if the selection mode was actually started.
     */
@@ -1747,38 +1734,65 @@ public class Editor {
        boolean selectionStarted = startSelectionActionModeWithSelectionInternal();
        if (selectionStarted) {
            getSelectionController().show();
        } else if (getInsertionController() != null) {
            getInsertionController().show();
        }
        return selectionStarted;
    }

    private boolean startSelectionActionModeWithSelectionInternal() {
    /**
     * If the TextView allows text selection, selects the current word when no existing selection
     * was available and starts a drag.
     *
     * @return true if the drag was started.
     */
    private boolean selectCurrentWordAndStartDrag() {
        if (extractedTextModeWillBeStarted()) {
            // Cancel the single tap delayed runnable.
            if (mSelectionModeWithoutSelectionRunnable != null) {
                mTextView.removeCallbacks(mSelectionModeWithoutSelectionRunnable);
            }

            return false;
        }

        if (mSelectionActionMode != null) {
            // Selection action mode is already started
            mSelectionActionMode.invalidate();
            mSelectionActionMode.finish();
        }
        if (!checkFieldAndSelectCurrentWord()) {
            return false;
        }
        getSelectionController().enterDrag();
        return true;
    }

    /**
     * Checks whether a selection can be performed on the current TextView and if so selects
     * the current word.
     *
     * @return true if there already was a selection or if the current word was selected.
     */
    private boolean checkFieldAndSelectCurrentWord() {
        if (!mTextView.canSelectText() || !mTextView.requestFocus()) {
            Log.w(TextView.LOG_TAG,
                    "TextView does not support text selection. Action mode cancelled.");
                    "TextView does not support text selection. Selection cancelled.");
            return false;
        }

        if (!mTextView.hasSelection()) {
            // There may already be a selection on device rotation
            if (!selectCurrentWord()) {
                // No word found under cursor or text selection not permitted.
            return selectCurrentWord();
        }
        return true;
    }

    private boolean startSelectionActionModeWithSelectionInternal() {
        if (mSelectionActionMode != null) {
            // Selection action mode is already started
            mSelectionActionMode.invalidate();
            return false;
        }

        if (!checkFieldAndSelectCurrentWord()) {
            return false;
        }

        boolean willExtract = extractedTextModeWillBeStarted();
@@ -4377,7 +4391,7 @@ public class Editor {
                            boolean stayedInArea = distanceSquared < doubleTapSlop * doubleTapSlop;

                            if (stayedInArea && isPositionOnText(eventX, eventY)) {
                                startSelectionActionModeWithSelectionAndStartDrag();
                                selectCurrentWordAndStartDrag();
                                mDiscardNextActionUp = true;
                            }
                        }
@@ -4480,6 +4494,7 @@ public class Editor {
                        mEndHandle.showAtLocation(endOffset);

                        // No longer the first dragging motion, reset.
                        startSelectionActionModeWithSelection();
                        mDragAcceleratorActive = false;
                        mStartOffset = -1;
                    }