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

Commit 27616de4 authored by Alan Viverette's avatar Alan Viverette Committed by Android (Google) Code Review
Browse files

Merge "Fix ViewRootImpl handling of content changes, fix ViewPager parenting"

parents 74e60ac9 34457f51
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -9959,6 +9959,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * @param oldt Previous vertical scroll origin.
     */
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        notifySubtreeAccessibilityStateChangedIfNeeded();
        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
            postSendViewScrolledAccessibilityEventCallback();
        }
+67 −29
Original line number Diff line number Diff line
@@ -6268,39 +6268,77 @@ public final class ViewRootImpl implements ViewParent,


            case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: {
                if (mAccessibilityFocusedHost != null && mAccessibilityFocusedVirtualView != null) {
                    // We care only for changes rooted in the focused host.
                    final long eventSourceId = event.getSourceNodeId();
                    final int hostViewId = AccessibilityNodeInfo.getAccessibilityViewId(
                            eventSourceId);
                    if (hostViewId != mAccessibilityFocusedHost.getAccessibilityViewId()) {
                        break;
                handleWindowContentChangedEvent(event);
            } break;
        }
        mAccessibilityManager.sendAccessibilityEvent(event);
        return true;
    }

    /**
     * Updates the focused virtual view, when necessary, in response to a
     * content changed event.
     * <p>
     * This is necessary to get updated bounds after a position change.
     *
     * @param event an accessibility event of type
     *              {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}
     */
    private void handleWindowContentChangedEvent(AccessibilityEvent event) {
        // No virtual view focused, nothing to do here.
        if (mAccessibilityFocusedHost == null || mAccessibilityFocusedVirtualView == null) {
            return;
        }

        // If we have a node but no provider, abort.
        final AccessibilityNodeProvider provider =
                mAccessibilityFocusedHost.getAccessibilityNodeProvider();
        if (provider == null) {
            // TODO: Should we clear the focused virtual view?
            return;
        }

                    // We only care about changes that may change the virtual focused view bounds.
        // We only care about change types that may affect the bounds of the
        // focused virtual view.
        final int changes = event.getContentChangeTypes();
                    if ((changes & AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE) != 0
                            || changes == AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED) {
                        AccessibilityNodeProvider provider = mAccessibilityFocusedHost
                                .getAccessibilityNodeProvider();
                        if (provider != null) {
                            final int virtualChildId = AccessibilityNodeInfo.getVirtualDescendantId(
                                    mAccessibilityFocusedVirtualView.getSourceNodeId());
                            if (virtualChildId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
                                mAccessibilityFocusedVirtualView = provider
                                        .createAccessibilityNodeInfo(
                                                AccessibilityNodeProvider.HOST_VIEW_ID);
        if ((changes & AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE) == 0
                && changes != AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED) {
            return;
        }

        final long eventSourceNodeId = event.getSourceNodeId();
        final int changedViewId = AccessibilityNodeInfo.getAccessibilityViewId(eventSourceNodeId);

        // Search up the tree for subtree containment.
        boolean hostInSubtree = false;
        View root = mAccessibilityFocusedHost;
        while (root != null && !hostInSubtree) {
            if (changedViewId == root.getAccessibilityViewId()) {
                hostInSubtree = true;
            } else {
                final ViewParent parent = root.getParent();
                if (parent instanceof View) {
                    root = (View) parent;
                } else {
                                mAccessibilityFocusedVirtualView = provider
                                        .createAccessibilityNodeInfo(virtualChildId);
                    root = null;
                }
            }
        }

        // We care only about changes in subtrees containing the host view.
        if (!hostInSubtree) {
            return;
        }
            } break;

        final long focusedSourceNodeId = mAccessibilityFocusedVirtualView.getSourceNodeId();
        int focusedChildId = AccessibilityNodeInfo.getVirtualDescendantId(focusedSourceNodeId);
        if (focusedChildId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
            // TODO: Should we clear the focused virtual view?
            focusedChildId = AccessibilityNodeProvider.HOST_VIEW_ID;
        }
        mAccessibilityManager.sendAccessibilityEvent(event);
        return true;

        // Refresh the node for the focused virtual view.
        mAccessibilityFocusedVirtualView = provider.createAccessibilityNodeInfo(focusedChildId);
    }

    @Override
+50 −71
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.accessibility.AccessibilityRecord;
import android.view.animation.Interpolator;
import android.widget.EdgeEffect;
@@ -371,8 +372,6 @@ public class ViewPager extends ViewGroup {
        mCloseEnough = (int) (CLOSE_ENOUGH * density);
        mDefaultGutterSize = (int) (DEFAULT_GUTTER_SIZE * density);

        setAccessibilityDelegate(new MyAccessibilityDelegate());

        if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
        }
@@ -2694,29 +2693,6 @@ public class ViewPager extends ViewGroup {
        return false;
    }

    @Override
    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
        // Dispatch scroll events from this ViewPager.
        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
            return super.dispatchPopulateAccessibilityEvent(event);
        }

        // Dispatch all other accessibility events from the current page.
        final int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() == VISIBLE) {
                final ItemInfo ii = infoForChild(child);
                if (ii != null && ii.position == mCurItem &&
                        child.dispatchPopulateAccessibilityEvent(event)) {
                    return true;
                }
            }
        }

        return false;
    }

    @Override
    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams();
@@ -2737,60 +2713,63 @@ public class ViewPager extends ViewGroup {
        return new LayoutParams(getContext(), attrs);
    }

    class MyAccessibilityDelegate extends AccessibilityDelegate {

    @Override
        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
            super.onInitializeAccessibilityEvent(host, event);
    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
        super.onInitializeAccessibilityEvent(event);

        event.setClassName(ViewPager.class.getName());
            final AccessibilityRecord record = AccessibilityRecord.obtain();
            record.setScrollable(canScroll());
            if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED
                    && mAdapter != null) {
                record.setItemCount(mAdapter.getCount());
                record.setFromIndex(mCurItem);
                record.setToIndex(mCurItem);
        event.setScrollable(canScroll());

        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED && mAdapter != null) {
            event.setItemCount(mAdapter.getCount());
            event.setFromIndex(mCurItem);
            event.setToIndex(mCurItem);
        }
    }

    @Override
        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
            super.onInitializeAccessibilityNodeInfo(host, info);
    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
        super.onInitializeAccessibilityNodeInfo(info);

        info.setClassName(ViewPager.class.getName());
        info.setScrollable(canScroll());

        if (canScrollHorizontally(1)) {
                info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
            info.addAction(AccessibilityAction.ACTION_SCROLL_FORWARD);
        }

        if (canScrollHorizontally(-1)) {
                info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
            info.addAction(AccessibilityAction.ACTION_SCROLL_BACKWARD);
        }
    }

    @Override
        public boolean performAccessibilityAction(View host, int action, Bundle args) {
            if (super.performAccessibilityAction(host, action, args)) {
    public boolean performAccessibilityAction(int action, Bundle args) {
        if (super.performAccessibilityAction(action, args)) {
            return true;
        }

        switch (action) {
                case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
            case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
                if (canScrollHorizontally(1)) {
                    setCurrentItem(mCurItem + 1);
                    return true;
                }
                } return false;
                case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
                return false;
            case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
                if (canScrollHorizontally(-1)) {
                    setCurrentItem(mCurItem - 1);
                    return true;
                }
                } return false;
                return false;
        }

        return false;
    }

    private boolean canScroll() {
            return (mAdapter != null) && (mAdapter.getCount() > 1);
        }
        return mAdapter != null && mAdapter.getCount() > 1;
    }

    private class PagerObserver extends DataSetObserver {