OSDN Git Service

Accessibiltiy: missed update to the previous patch.
authorSvetoslav <svetoslavganov@google.com>
Tue, 10 Feb 2015 01:14:28 +0000 (17:14 -0800)
committerSvetoslav <svetoslavganov@google.com>
Tue, 10 Feb 2015 02:33:07 +0000 (18:33 -0800)
Change-Id: I4c47d38f5e137dcc1c6db0561b3824a26572027d

core/java/android/view/ViewGroup.java
core/java/android/view/ViewRootImpl.java

index 2182127..c4b689f 100644 (file)
@@ -1983,6 +1983,15 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
             TouchTarget newTouchTarget = null;
             boolean alreadyDispatchedToNewTouchTarget = false;
             if (!canceled && !intercepted) {
+
+                // If the event is targeting accessiiblity focus we give it to the
+                // view that has accessibility focus and if it does not handle it
+                // we clear the flag and dispatch the event to all children as usual.
+                // We are looking up the accessibility focused host to avoid keeping
+                // state since these events are very rare.
+                View childWithAccessibilityFocus = ev.isTargetAccessibilityFocus()
+                        ? findChildWithAccessibilityFocus() : null;
+
                 if (actionMasked == MotionEvent.ACTION_DOWN
                         || (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN)
                         || actionMasked == MotionEvent.ACTION_HOVER_MOVE) {
@@ -2009,8 +2018,22 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
                                     ? getChildDrawingOrder(childrenCount, i) : i;
                             final View child = (preorderedList == null)
                                     ? children[childIndex] : preorderedList.get(childIndex);
+
+                            // If there is a view that has accessibility focus we want it
+                            // to get the event first and if not handled we will perform a
+                            // normal dispatch. We may do a double iteration but this is
+                            // safer given the timeframe.
+                            if (childWithAccessibilityFocus != null) {
+                                if (childWithAccessibilityFocus != child) {
+                                    continue;
+                                }
+                                childWithAccessibilityFocus = null;
+                                i = childrenCount - 1;
+                            }
+
                             if (!canViewReceivePointerEvents(child)
                                     || !isTransformedTouchPointInView(x, y, child, null)) {
+                                ev.setTargetAccessibilityFocus(false);
                                 continue;
                             }
 
@@ -2043,6 +2066,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
                                 alreadyDispatchedToNewTouchTarget = true;
                                 break;
                             }
+
+                            // The accessibility focus didn't handle the event, so clear
+                            // the flag and do a normal dispatch to all children.
+                            ev.setTargetAccessibilityFocus(false);
                         }
                         if (preorderedList != null) preorderedList.clear();
                     }
@@ -2115,6 +2142,34 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
     }
 
     /**
+     * Finds the child which has accessibility focus.
+     *
+     * @return The child that has focus.
+     */
+    private View findChildWithAccessibilityFocus() {
+        ViewRootImpl viewRoot = getViewRootImpl();
+        if (viewRoot == null) {
+            return null;
+        }
+
+        View current = viewRoot.getAccessibilityFocusedHost();
+        if (current == null) {
+            return null;
+        }
+
+        ViewParent parent = current.getParent();
+        while (parent instanceof View) {
+            if (parent == this) {
+                return current;
+            }
+            current = (View) parent;
+            parent = current.getParent();
+        }
+
+        return null;
+    }
+
+    /**
      * Resets all touch state in preparation for a new cycle.
      */
     private void resetTouchState() {
index 15d47ba..e4d82b1 100644 (file)
@@ -4121,13 +4121,6 @@ public final class ViewRootImpl implements ViewParent,
 
             mAttachInfo.mUnbufferedDispatchRequested = false;
             boolean handled = mView.dispatchPointerEvent(event);
-            if (!handled && event.isTargetAccessibilityFocus()) {
-                // The event was targeting accessibility focused view and is not handled,
-                // it is very rare but possible that a predecessor of the focused view handles
-                // the event but didn't due to special dispatch, perform normal event dispatch.
-                event.setTargetAccessibilityFocus(false);
-                handled = mView.dispatchPointerEvent(event);
-            }
             if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) {
                 mUnbufferedInputDispatch = true;
                 if (mConsumeBatchedInputScheduled) {