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

Commit 9d575063 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 8593

* changes:
  When you double-tap a word in an EditText, select the word.
parents 17dcc73a a6e50454
Loading
Loading
Loading
Loading
+81 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.graphics.Rect;
import android.text.*;
import android.widget.TextView;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.MotionEvent;

// XXX this doesn't extend MetaKeyKeyListener because the signatures
@@ -256,8 +257,32 @@ implements MovementMethod
                              (MetaKeyKeyListener.getMetaState(buffer,
                                MetaKeyKeyListener.META_SELECTING) != 0);

                DoubleTapState[] tap = buffer.getSpans(0, buffer.length(),
                                                       DoubleTapState.class);
                boolean doubletap = false;

                if (tap.length > 0) {
                    if (event.getEventTime() - tap[0].mWhen <=
                        ViewConfiguration.getDoubleTapTimeout()) {
                        if (sameWord(buffer, off, Selection.getSelectionEnd(buffer))) {
                            doubletap = true;
                        }
                    }

                    tap[0].mWhen = event.getEventTime();
                } else {
                    DoubleTapState newtap = new DoubleTapState();
                    newtap.mWhen = event.getEventTime();
                    buffer.setSpan(newtap, 0, buffer.length(),
                                   Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                }

                if (cap) {
                    Selection.extendSelection(buffer, off);
                } else if (doubletap) {
                    Selection.setSelection(buffer,
                                           findWordStart(buffer, off),
                                           findWordEnd(buffer, off));
                } else {
                    Selection.setSelection(buffer, off);
                }
@@ -272,6 +297,62 @@ implements MovementMethod
        return handled;
    }

    private static class DoubleTapState implements NoCopySpan {
        long mWhen;
    }

    private static boolean sameWord(CharSequence text, int one, int two) {
        int start = findWordStart(text, one);
        int end = findWordEnd(text, one);

        if (end == start) {
            return false;
        }

        return start == findWordStart(text, two) &&
               end == findWordEnd(text, two);
    }

    // TODO: Unify with TextView.getWordForDictionary()
    private static int findWordStart(CharSequence text, int start) {
        for (; start > 0; start--) {
            char c = text.charAt(start - 1);
            int type = Character.getType(c);

            if (c != '\'' &&
                type != Character.UPPERCASE_LETTER &&
                type != Character.LOWERCASE_LETTER &&
                type != Character.TITLECASE_LETTER &&
                type != Character.MODIFIER_LETTER &&
                type != Character.DECIMAL_DIGIT_NUMBER) {
                break;
            }
        }

        return start;
    }

    // TODO: Unify with TextView.getWordForDictionary()
    private static int findWordEnd(CharSequence text, int end) {
        int len = text.length();

        for (; end < len; end++) {
            char c = text.charAt(end);
            int type = Character.getType(c);

            if (c != '\'' &&
                type != Character.UPPERCASE_LETTER &&
                type != Character.LOWERCASE_LETTER &&
                type != Character.TITLECASE_LETTER &&
                type != Character.MODIFIER_LETTER &&
                type != Character.DECIMAL_DIGIT_NUMBER) {
                break;
            }
        }

        return end;
    }

    public boolean canSelectArbitrarily() {
        return true;
    }