diff options
Diffstat (limited to 'android/view/ViewGroup.java')
-rw-r--r-- | android/view/ViewGroup.java | 173 |
1 files changed, 127 insertions, 46 deletions
diff --git a/android/view/ViewGroup.java b/android/view/ViewGroup.java index 4631261e..6002fe51 100644 --- a/android/view/ViewGroup.java +++ b/android/view/ViewGroup.java @@ -583,6 +583,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager private List<Integer> mTransientIndices = null; private List<View> mTransientViews = null; + /** + * Keeps track of how many child views have UnhandledKeyEventListeners. This should only be + * updated on the UI thread so shouldn't require explicit synchronization. + */ + int mChildUnhandledKeyListeners = 0; /** * Empty ActionMode used as a sentinel in recursive entries to startActionModeForChild. @@ -3555,13 +3560,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager public void dispatchProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) { super.dispatchProvideAutofillStructure(structure, flags); + if (structure.getChildCount() != 0) { return; } if (!isLaidOut()) { - Log.v(VIEW_LOG_TAG, "dispatchProvideAutofillStructure(): not laid out, ignoring " - + mChildrenCount + " children of " + getAutofillId()); + if (Helper.sVerbose) { + Log.v(VIEW_LOG_TAG, "dispatchProvideAutofillStructure(): not laid out, ignoring " + + mChildrenCount + " children of " + getAutofillId()); + } return; } @@ -3649,34 +3657,44 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return ViewGroup.class.getName(); } + @Override + public void notifySubtreeAccessibilityStateChanged(View child, View source, int changeType) { + // If this is a live region, we should send a subtree change event + // from this view. Otherwise, we can let it propagate up. + if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) { + notifyViewAccessibilityStateChangedIfNeeded( + AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE); + } else if (mParent != null) { + try { + mParent.notifySubtreeAccessibilityStateChanged(this, source, changeType); + } catch (AbstractMethodError e) { + Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + + " does not fully implement ViewParent", e); + } + } + } + /** @hide */ @Override - public void notifyAccessibilitySubtreeChanged() { + public void notifySubtreeAccessibilityStateChangedIfNeeded() { if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) { return; } // If something important for a11y is happening in this subtree, make sure it's dispatched // from a view that is important for a11y so it doesn't get lost. - if (getImportantForAccessibility() != IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS - && !isImportantForAccessibility() - && getChildCount() > 0) { + if ((getImportantForAccessibility() != IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) + && !isImportantForAccessibility() && (getChildCount() > 0)) { ViewParent a11yParent = getParentForAccessibility(); if (a11yParent instanceof View) { - ((View) a11yParent).notifyAccessibilitySubtreeChanged(); + ((View) a11yParent).notifySubtreeAccessibilityStateChangedIfNeeded(); return; } } - super.notifyAccessibilitySubtreeChanged(); - } - - @Override - public void notifySubtreeAccessibilityStateChanged(View child, View source, int changeType) { - notifyAccessibilityStateChanged(source, changeType); + super.notifySubtreeAccessibilityStateChangedIfNeeded(); } - /** @hide */ @Override - public void resetSubtreeAccessibilityStateChanged() { + void resetSubtreeAccessibilityStateChanged() { super.resetSubtreeAccessibilityStateChanged(); View[] children = mChildren; final int childCount = mChildrenCount; @@ -3958,15 +3976,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } /** - * Layout debugging code which draws rectangles around layout params. - * - * <p>This function is called automatically when the developer setting is enabled.<p/> - * - * <p>It is strongly advised to only call this function from debug builds as there is - * a risk of leaking unwanted layout information.<p/> - * - * @param canvas the canvas on which to draw - * @param paint the paint used to draw through + * @hide */ protected void onDebugDrawMargins(Canvas canvas, Paint paint) { for (int i = 0; i < getChildCount(); i++) { @@ -3976,19 +3986,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } /** - * Layout debugging code which draws rectangles around: - * <ul> - * <li>optical bounds<li/> - * <li>margins<li/> - * <li>clip bounds<li/> - * <ul/> - * - * <p>This function is called automatically when the developer setting is enabled.<p/> - * - * <p>It is strongly advised to only call this function from debug builds as there is - * a risk of leaking unwanted layout information.<p/> - * - * @param canvas the canvas on which to draw + * @hide */ protected void onDebugDraw(Canvas canvas) { Paint paint = getDebugPaint(); @@ -4292,6 +4290,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager recreateChildDisplayList(child); } } + final int transientCount = mTransientViews == null ? 0 : mTransientIndices.size(); + for (int i = 0; i < transientCount; ++i) { + View child = mTransientViews.get(i); + if (((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null)) { + recreateChildDisplayList(child); + } + } if (mOverlay != null) { View overlayView = mOverlay.getOverlayView(); recreateChildDisplayList(overlayView); @@ -5055,6 +5060,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager child.assignParent(this); } else { child.mParent = this; + if (child.hasUnhandledKeyListener()) { + incrementChildUnhandledKeyListeners(); + } } final boolean childHasFocus = child.hasFocus(); @@ -5088,7 +5096,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } if (child.getVisibility() != View.GONE) { - notifyAccessibilitySubtreeChanged(); + notifySubtreeAccessibilityStateChangedIfNeeded(); } if (mTransientIndices != null) { @@ -5110,6 +5118,20 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager // manually assembling the hierarchy, update the ancestor default-focus chain. setDefaultFocus(child); } + + touchAccessibilityNodeProviderIfNeeded(child); + } + + /** + * We may need to touch the provider to bring up the a11y layer. In a11y mode + * clients inspect the screen or the user touches it which triggers bringing up + * of the a11y infrastructure while in autofill mode we want the infra up and + * running from the beginning since we watch for a11y events to drive autofill. + */ + private void touchAccessibilityNodeProviderIfNeeded(View child) { + if (mContext.isAutofillCompatibilityEnabled()) { + child.getAccessibilityNodeProvider(); + } } private void addInArray(View child, int index) { @@ -5345,6 +5367,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager removeFromArray(index); + if (view.hasUnhandledKeyListener()) { + decrementChildUnhandledKeyListeners(); + } + if (view == mDefaultFocus) { clearDefaultFocus(view); } @@ -5358,7 +5384,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager dispatchViewRemoved(view); if (view.getVisibility() != View.GONE) { - notifyAccessibilitySubtreeChanged(); + notifySubtreeAccessibilityStateChangedIfNeeded(); } int transientCount = mTransientIndices == null ? 0 : mTransientIndices.size(); @@ -6077,7 +6103,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (invalidate) { invalidateViewProperty(false, false); } - notifyAccessibilitySubtreeChanged(); + notifySubtreeAccessibilityStateChangedIfNeeded(); } @Override @@ -7523,6 +7549,62 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } + @Override + boolean hasUnhandledKeyListener() { + return (mChildUnhandledKeyListeners > 0) || super.hasUnhandledKeyListener(); + } + + void incrementChildUnhandledKeyListeners() { + mChildUnhandledKeyListeners += 1; + if (mChildUnhandledKeyListeners == 1) { + if (mParent instanceof ViewGroup) { + ((ViewGroup) mParent).incrementChildUnhandledKeyListeners(); + } + } + } + + void decrementChildUnhandledKeyListeners() { + mChildUnhandledKeyListeners -= 1; + if (mChildUnhandledKeyListeners == 0) { + if (mParent instanceof ViewGroup) { + ((ViewGroup) mParent).decrementChildUnhandledKeyListeners(); + } + } + } + + @Override + View dispatchUnhandledKeyEvent(KeyEvent evt) { + if (!hasUnhandledKeyListener()) { + return null; + } + ArrayList<View> orderedViews = buildOrderedChildList(); + if (orderedViews != null) { + try { + for (int i = orderedViews.size() - 1; i >= 0; --i) { + View v = orderedViews.get(i); + View consumer = v.dispatchUnhandledKeyEvent(evt); + if (consumer != null) { + return consumer; + } + } + } finally { + orderedViews.clear(); + } + } else { + for (int i = getChildCount() - 1; i >= 0; --i) { + View v = getChildAt(i); + View consumer = v.dispatchUnhandledKeyEvent(evt); + if (consumer != null) { + return consumer; + } + } + } + if (onUnhandledKeyEvent(evt)) { + return this; + } + return null; + } + /** * LayoutParams are used by views to tell their parents how they want to be * laid out. See @@ -7705,14 +7787,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager /** * Use {@code canvas} to draw suitable debugging annotations for these LayoutParameters. * - * <p>This function is called automatically when the developer setting is enabled.<p/> - * - * <p>It is strongly advised to only call this function from debug builds as there is - * a risk of leaking unwanted layout information.<p/> - * * @param view the view that contains these layout parameters * @param canvas the canvas on which to draw - * @param paint the paint used to draw through + * + * @hide */ public void onDebugDraw(View view, Canvas canvas, Paint paint) { } @@ -8216,6 +8294,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return ((mMarginFlags & LAYOUT_DIRECTION_MASK) == View.LAYOUT_DIRECTION_RTL); } + /** + * @hide + */ @Override public void onDebugDraw(View view, Canvas canvas, Paint paint) { Insets oi = isLayoutModeOptical(view.mParent) ? view.getOpticalInsets() : Insets.NONE; |