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

Commit 69b495bd authored by George Mount's avatar George Mount Committed by Android (Google) Code Review
Browse files

Merge "Alt-up moves focus to the toolbar in action bar mode."

parents 7f55215a 5beb2617
Loading
Loading
Loading
Loading
+97 −0
Original line number Diff line number Diff line
@@ -31,9 +31,11 @@ import android.view.ActionMode;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewHierarchyEncoder;
import android.view.ViewParent;
import android.view.Window;
import android.widget.SpinnerAdapter;
import java.lang.annotation.Retention;
@@ -1070,6 +1072,62 @@ public abstract class ActionBar {
    public void setWindowTitle(CharSequence title) {
    }

    /**
     * Attempts to move focus to the ActionBar if it does not already contain the focus.
     *
     * @return {@code true} if focus changes or {@code false} if focus doesn't change.
     * @hide
     */
    public boolean requestFocus() {
        return false;
    }

    /**
     * Common implementation for requestFocus that takes in the Toolbar and moves focus
     * to the contents. This makes the ViewGroups containing the toolbar allow focus while it stays
     * in the ActionBar and then prevents it again once it leaves.
     *
     * @param viewGroup The toolbar ViewGroup
     * @return {@code true} if focus changes or {@code false} if focus doesn't change.
     * @hide
     */
    protected boolean requestFocus(ViewGroup viewGroup) {
        if (viewGroup != null && !viewGroup.hasFocus()) {
            final ViewGroup toolbar = viewGroup.getTouchscreenBlocksFocus() ? viewGroup : null;
            ViewParent parent = viewGroup.getParent();
            ViewGroup container = null;
            while (parent != null && parent instanceof ViewGroup) {
                final ViewGroup vgParent = (ViewGroup) parent;
                if (vgParent.getTouchscreenBlocksFocus()) {
                    container = vgParent;
                    break;
                }
                parent = vgParent.getParent();
            }
            if (container != null) {
                container.setTouchscreenBlocksFocus(false);
            }
            if (toolbar != null) {
                toolbar.setTouchscreenBlocksFocus(false);
            }
            viewGroup.requestFocus();
            final View focused = viewGroup.findFocus();
            if (focused != null) {
                focused.setOnFocusChangeListener(new FollowOutOfActionBar(viewGroup,
                        container, toolbar));
            } else {
                if (container != null) {
                    container.setTouchscreenBlocksFocus(true);
                }
                if (toolbar != null) {
                    toolbar.setTouchscreenBlocksFocus(true);
                }
            }
            return true;
        }
        return false;
    }

    /**
     * Listener interface for ActionBar navigation events.
     *
@@ -1388,4 +1446,43 @@ public abstract class ActionBar {
            encoder.addProperty("gravity", gravity);
        }
    }

    /**
     * Tracks the focused View until it leaves the ActionBar, then it resets the
     * touchscreenBlocksFocus value.
     */
    private static class FollowOutOfActionBar implements OnFocusChangeListener, Runnable {
        private final ViewGroup mFocusRoot;
        private final ViewGroup mContainer;
        private final ViewGroup mToolbar;

        public FollowOutOfActionBar(ViewGroup focusRoot, ViewGroup container, ViewGroup toolbar) {
            mContainer = container;
            mToolbar = toolbar;
            mFocusRoot = focusRoot;
        }

        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (!hasFocus) {
                v.setOnFocusChangeListener(null);
                final View focused = mFocusRoot.findFocus();
                if (focused != null) {
                    focused.setOnFocusChangeListener(this);
                } else {
                    mFocusRoot.post(this);
                }
            }
        }

        @Override
        public void run() {
            if (mContainer != null) {
                mContainer.setTouchscreenBlocksFocus(true);
            }
            if (mToolbar != null) {
                mToolbar.setTouchscreenBlocksFocus(true);
            }
        }
    }
}
+18 −1
Original line number Diff line number Diff line
@@ -816,6 +816,7 @@ public class Activity extends ContextThemeWrapper
    SharedElementCallback mExitTransitionListener = SharedElementCallback.NULL_CALLBACK;

    private boolean mHasCurrentPermissionsRequest;
    private boolean mEatKeyUpEvent;

    /** Return the intent that started this activity. */
    public Intent getIntent() {
@@ -2827,9 +2828,25 @@ public class Activity extends ContextThemeWrapper

        // Let action bars open menus in response to the menu key prioritized over
        // the window handling it
        if (event.getKeyCode() == KeyEvent.KEYCODE_MENU &&
        final int keyCode = event.getKeyCode();
        if (keyCode == KeyEvent.KEYCODE_MENU &&
                mActionBar != null && mActionBar.onMenuKeyEvent(event)) {
            return true;
        } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
            // Capture the Alt-up and send focus to the ActionBar
            final int action = event.getAction();
            if (action == KeyEvent.ACTION_DOWN) {
                if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
                    final ActionBar actionBar = getActionBar();
                    if (actionBar != null && actionBar.isShowing() && actionBar.requestFocus()) {
                        mEatKeyUpEvent = true;
                        return true;
                    }
                }
            } else if (action == KeyEvent.ACTION_UP && mEatKeyUpEvent) {
                mEatKeyUpEvent = false;
                return true;
            }
        }

        Window win = getWindow();
+10 −0
Original line number Diff line number Diff line
@@ -29,10 +29,14 @@ import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.Window;
import android.view.WindowCallbackWrapper;
import android.widget.SpinnerAdapter;
import android.widget.Toolbar;

import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuPresenter;
import com.android.internal.widget.DecorToolbar;
@@ -499,6 +503,12 @@ public class ToolbarActionBar extends ActionBar {
        }
    }

    /** @hide */
    @Override
    public boolean requestFocus() {
        return requestFocus(mDecorToolbar.getViewGroup());
    }

    private class ToolbarCallbackWrapper extends WindowCallbackWrapper {
        public ToolbarCallbackWrapper(Window.Callback wrapped) {
            super(wrapped);
+8 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.internal.app;

import android.animation.ValueAnimator;
import android.content.res.TypedArray;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.Toolbar;

@@ -950,6 +952,12 @@ public class WindowDecorActionBar extends ActionBar implements
        return false;
    }

    /** @hide */
    @Override
    public boolean requestFocus() {
        return requestFocus(mDecorToolbar.getViewGroup());
    }

    /**
     * @hide
     */