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

Commit 44fbbca3 authored by Youngsang Cho's avatar Youngsang Cho
Browse files

Properly handle navigation keys in TIS

If the navigation keys are dispatched to an overlay view and
the overlay view has focusable views, the navigation keys should
be always handled.

Bug: 15174809
Change-Id: Ia7490880243342e08e4502644e1864e4c583ee1d
parent 19bb5705
Loading
Loading
Loading
Loading
+36 −3
Original line number Diff line number Diff line
@@ -560,8 +560,11 @@ public abstract class TvInputService extends Service {
         */
        int dispatchInputEvent(InputEvent event, InputEventReceiver receiver) {
            if (DEBUG) Log.d(TAG, "dispatchInputEvent(" + event + ")");
            boolean isNavigationKey = false;
            if (event instanceof KeyEvent) {
                if (((KeyEvent) event).dispatch(this, mDispatcherState, this)) {
                KeyEvent keyEvent = (KeyEvent) event;
                isNavigationKey = isNavigationKey(keyEvent.getKeyCode());
                if (keyEvent.dispatch(this, mDispatcherState, this)) {
                    return TvInputManager.Session.DISPATCH_HANDLED;
                }
            } else if (event instanceof MotionEvent) {
@@ -587,15 +590,45 @@ public abstract class TvInputService extends Service {
            if (!mOverlayView.hasWindowFocus()) {
                mOverlayView.getViewRootImpl().windowFocusChanged(true, true);
            }
            if (isNavigationKey && mOverlayView.hasFocusable()) {
                // If mOverlayView has focusable views, navigation key events should be always
                // handled. If not, it can make the application UI navigation messed up.
                // For example, in the case that the left-most view is focused, a left key event
                // will not be handled in ViewRootImpl. Then, the left key event will be handled in
                // the application during the UI navigation of the TV input.
                mOverlayView.getViewRootImpl().dispatchInputEvent(event);
                return TvInputManager.Session.DISPATCH_HANDLED;
            } else {
                mOverlayView.getViewRootImpl().dispatchInputEvent(event, receiver);
                return TvInputManager.Session.DISPATCH_IN_PROGRESS;
            }
        }

        private void setSessionCallback(ITvInputSessionCallback callback) {
            mSessionCallback = callback;
        }
    }

    /** @hide */
    public static boolean isNavigationKey(int keyCode) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_LEFT:
            case KeyEvent.KEYCODE_DPAD_RIGHT:
            case KeyEvent.KEYCODE_DPAD_UP:
            case KeyEvent.KEYCODE_DPAD_DOWN:
            case KeyEvent.KEYCODE_DPAD_CENTER:
            case KeyEvent.KEYCODE_PAGE_UP:
            case KeyEvent.KEYCODE_PAGE_DOWN:
            case KeyEvent.KEYCODE_MOVE_HOME:
            case KeyEvent.KEYCODE_MOVE_END:
            case KeyEvent.KEYCODE_TAB:
            case KeyEvent.KEYCODE_SPACE:
            case KeyEvent.KEYCODE_ENTER:
                return true;
        }
        return false;
    }

    private final class ServiceHandler extends Handler {
        private static final int DO_CREATE_SESSION = 1;
        private static final int DO_BROADCAST_AVAILABILITY_CHANGE = 2;