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

Commit 88c11754 authored by Adam Powell's avatar Adam Powell
Browse files

Allow focusable in touch mode views to ignore touchscreen focus blocks

Bug 16284253

Change-Id: I7cddf1988b0c24ae3050a13d2ce6fb3143d8aade
parent f89bff9e
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -5048,8 +5048,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     *         View, false otherwise.
     *
     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
     * @see ViewGroup#getTouchscreenBlocksFocus()
     */
    public boolean hasFocusable() {
        if (!isFocusableInTouchMode()) {
            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
                final ViewGroup g = (ViewGroup) p;
                if (g.shouldBlockFocusForTouchscreen()) {
                    return false;
                }
            }
        }
        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
    }
@@ -7439,11 +7448,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * @return Whether any ancestor of this view blocks descendant focus.
     */
    private boolean hasAncestorThatBlocksDescendantFocus() {
        final boolean focusableInTouchMode = isFocusableInTouchMode();
        ViewParent ancestor = mParent;
        while (ancestor instanceof ViewGroup) {
            final ViewGroup vgAncestor = (ViewGroup) ancestor;
            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
                    || vgAncestor.shouldBlockFocusForTouchscreen()) {
                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
                return true;
            } else {
                ancestor = vgAncestor.getParent();
+26 −13
Original line number Diff line number Diff line
@@ -669,7 +669,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
                // shortcut: don't report a new focusable view if we block our descendants from
                // getting focus
                && (getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS)
                && !shouldBlockFocusForTouchscreen()
                && (isFocusableInTouchMode() || !shouldBlockFocusForTouchscreen())
                // shortcut: don't report a new focusable view if we already are focused
                // (and we don't prefer our descendants)
                //
@@ -865,6 +865,17 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        return mFocused;
    }

    View getDeepestFocusedChild() {
        View v = this;
        while (v != null) {
            if (v.isFocused()) {
                return v;
            }
            v = v instanceof ViewGroup ? ((ViewGroup) v).getFocusedChild() : null;
        }
        return null;
    }

    /**
     * Returns true if this view has or contains focus
     *
@@ -911,8 +922,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        }

        final int descendantFocusability = getDescendantFocusability();
        if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS &&
                !shouldBlockFocusForTouchscreen()) {
        if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
            final int count = mChildrenCount;
            final View[] children = mChildren;

@@ -936,8 +946,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager

        final int descendantFocusability = getDescendantFocusability();

        if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS &&
                !shouldBlockFocusForTouchscreen()) {
        if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
            if (shouldBlockFocusForTouchscreen()) {
                focusableMode |= FOCUSABLES_TOUCH_MODE;
            }

            final int count = mChildrenCount;
            final View[] children = mChildren;

@@ -955,7 +968,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        // among the focusable children would be more interesting.
        if ((descendantFocusability != FOCUS_AFTER_DESCENDANTS
                // No focusable descendants
                || (focusableCount == views.size())) && !shouldBlockFocusForTouchscreen()) {
                || (focusableCount == views.size())) &&
                (isFocusableInTouchMode() || !shouldBlockFocusForTouchscreen())) {
            super.addFocusables(views, direction, focusableMode);
        }
    }
@@ -971,11 +985,14 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        if (touchscreenBlocksFocus) {
            mGroupFlags |= FLAG_TOUCHSCREEN_BLOCKS_FOCUS;
            if (hasFocus()) {
                final View focusedChild = getDeepestFocusedChild();
                if (!focusedChild.isFocusableInTouchMode()) {
                    final View newFocus = focusSearch(FOCUS_FORWARD);
                    if (newFocus != null) {
                        newFocus.requestFocus();
                    }
                }
            }
        } else {
            mGroupFlags &= ~FLAG_TOUCHSCREEN_BLOCKS_FOCUS;
        }
@@ -2485,10 +2502,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        }
        int descendantFocusability = getDescendantFocusability();

        if (shouldBlockFocusForTouchscreen()) {
            return false;
        }

        switch (descendantFocusability) {
            case FOCUS_BLOCK_DESCENDANTS:
                return super.requestFocus(direction, previouslyFocusedRect);