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

Commit 53cfed57 authored by Evan Rosky's avatar Evan Rosky
Browse files

Only restrict arrows out of text fields from keyboard

Otherwise, TV remotes and gamepads will get stuck in text
fields since they lack TAB key.

Started with revert of commit d4cef42b.

Bug: 37502292
Test: Added a CTS. Manually tested with BT keyboard (Pixel C) and
      BT gamepad.
Change-Id: Iff7e0bf714605555d4fb49d3e5e2680117b3af5b
parent 4f3ba1ae
Loading
Loading
Loading
Loading
+32 −3
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ import android.view.ContextMenu;
import android.view.DragEvent;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -369,6 +370,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener

    private TextClassifier mTextClassifier;

    // A flag to prevent repeated movements from escaping the enclosing text view. The idea here is
    // that if a user is holding down a movement key to traverse text, we shouldn't also traverse
    // the view hierarchy. On the other hand, if the user is using the movement key to traverse
    // views (i.e. the first movement was to traverse out of this view, or this view was traversed
    // into by the user holding the movement key down) then we shouldn't prevent the focus from
    // changing.
    private boolean mPreventDefaultMovement;

    private TextUtils.TruncateAt mEllipsize;

    static class Drawables {
@@ -7090,6 +7099,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            return KEY_EVENT_NOT_HANDLED;
        }

        // If this is the initial keydown, we don't want to prevent a movement away from this view.
        // While this shouldn't be necessary because any time we're preventing default movement we
        // should be restricting the focus to remain within this view, thus we'll also receive
        // the key up event, occasionally key up events will get dropped and we don't want to
        // prevent the user from traversing out of this on the next key down.
        if (event.getRepeatCount() == 0 && !KeyEvent.isModifierKey(keyCode)) {
            mPreventDefaultMovement = false;
        }

        switch (keyCode) {
            case KeyEvent.KEYCODE_ENTER:
                if (event.hasNoModifiers()) {
@@ -7221,16 +7239,23 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            }
            if (doDown) {
                if (mMovement.onKeyDown(this, (Spannable) mText, keyCode, event)) {
                    if (event.getRepeatCount() == 0 && !KeyEvent.isModifierKey(keyCode)) {
                        mPreventDefaultMovement = true;
                    }
                    return KEY_DOWN_HANDLED_BY_MOVEMENT_METHOD;
                }
            }
            // Consume arrows to prevent focus leaving the editor.
            if (isDirectionalNavigationKey(keyCode)) {
            // Consume arrows from keyboard devices to prevent focus leaving the editor.
            // DPAD/JOY devices (Gamepads, TV remotes) often lack a TAB key so allow those
            // to move focus with arrows.
            if (event.getSource() == InputDevice.SOURCE_KEYBOARD
                    && isDirectionalNavigationKey(keyCode)) {
                return KEY_EVENT_HANDLED;
            }
        }

        return KEY_EVENT_NOT_HANDLED;
        return mPreventDefaultMovement && !KeyEvent.isModifierKey(keyCode)
                ? KEY_EVENT_HANDLED : KEY_EVENT_NOT_HANDLED;
    }

    /**
@@ -7263,6 +7288,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            return super.onKeyUp(keyCode, event);
        }

        if (!KeyEvent.isModifierKey(keyCode)) {
            mPreventDefaultMovement = false;
        }

        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_CENTER:
                if (event.hasNoModifiers()) {