Loading core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl +0 −4 Original line number Diff line number Diff line Loading @@ -54,10 +54,6 @@ interface IAccessibilityServiceConnection { int action, in Bundle arguments, int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId); boolean computeClickPointInScreen(int accessibilityWindowId, long accessibilityNodeId, int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId); AccessibilityWindowInfo getWindow(int windowId); List<AccessibilityWindowInfo> getWindows(); Loading core/java/android/view/AccessibilityInteractionController.java +0 −95 Original line number Diff line number Diff line Loading @@ -636,95 +636,6 @@ final class AccessibilityInteractionController { } } public void computeClickPointInScreenClientThread(long accessibilityNodeId, Region interactiveRegion, int interactionId, IAccessibilityInteractionConnectionCallback callback, int interrogatingPid, long interrogatingTid, MagnificationSpec spec) { Message message = mHandler.obtainMessage(); message.what = PrivateHandler.MSG_COMPUTE_CLICK_POINT_IN_SCREEN; SomeArgs args = SomeArgs.obtain(); args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId); args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId); args.argi3 = interactionId; args.arg1 = callback; args.arg2 = spec; args.arg3 = interactiveRegion; message.obj = args; // If the interrogation is performed by the same thread as the main UI // thread in this process, set the message as a static reference so // after this call completes the same thread but in the interrogating // client can handle the message to generate the result. if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) { AccessibilityInteractionClient.getInstanceForThread( interrogatingTid).setSameThreadMessage(message); } else { mHandler.sendMessage(message); } } private void computeClickPointInScreenUiThread(Message message) { SomeArgs args = (SomeArgs) message.obj; final int accessibilityViewId = args.argi1; final int virtualDescendantId = args.argi2; final int interactionId = args.argi3; final IAccessibilityInteractionConnectionCallback callback = (IAccessibilityInteractionConnectionCallback) args.arg1; final MagnificationSpec spec = (MagnificationSpec) args.arg2; final Region interactiveRegion = (Region) args.arg3; args.recycle(); boolean succeeded = false; Point point = mTempPoint; try { if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) { return; } View target = null; if (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { target = findViewByAccessibilityId(accessibilityViewId); } else { target = mViewRootImpl.mView; } if (target != null && isShown(target)) { AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider(); if (provider != null) { // For virtual views just use the center of the bounds in screen. AccessibilityNodeInfo node = null; if (virtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { node = provider.createAccessibilityNodeInfo(virtualDescendantId); } else { node = provider.createAccessibilityNodeInfo( AccessibilityNodeProvider.HOST_VIEW_ID); } if (node != null) { succeeded = true; Rect boundsInScreen = mTempRect; node.getBoundsInScreen(boundsInScreen); point.set(boundsInScreen.centerX(), boundsInScreen.centerY()); } } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { // For a real view, ask the view to compute the click point. succeeded = target.computeClickPointInScreenForAccessibility( interactiveRegion, point); } } } finally { try { Point result = null; if (succeeded) { applyAppScaleAndMagnificationSpecIfNeeded(point, spec); result = point; } callback.setComputeClickPointInScreenActionResult(result, interactionId); } catch (RemoteException re) { /* ignore - the other side will time out */ } } } private View findViewByAccessibilityId(int accessibilityId) { View root = mViewRootImpl.mView; if (root == null) { Loading Loading @@ -1201,7 +1112,6 @@ final class AccessibilityInteractionController { private final static int MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT = 4; private final static int MSG_FIND_FOCUS = 5; private final static int MSG_FOCUS_SEARCH = 6; private final static int MSG_COMPUTE_CLICK_POINT_IN_SCREEN = 7; public PrivateHandler(Looper looper) { super(looper); Loading @@ -1223,8 +1133,6 @@ final class AccessibilityInteractionController { return "MSG_FIND_FOCUS"; case MSG_FOCUS_SEARCH: return "MSG_FOCUS_SEARCH"; case MSG_COMPUTE_CLICK_POINT_IN_SCREEN: return "MSG_COMPUTE_CLICK_POINT_IN_SCREEN"; default: throw new IllegalArgumentException("Unknown message type: " + type); } Loading Loading @@ -1252,9 +1160,6 @@ final class AccessibilityInteractionController { case MSG_FOCUS_SEARCH: { focusSearchUiThread(message); } break; case MSG_COMPUTE_CLICK_POINT_IN_SCREEN: { computeClickPointInScreenUiThread(message); } break; default: throw new IllegalArgumentException("Unknown message type: " + type); } Loading core/java/android/view/MotionEvent.java +31 −0 Original line number Diff line number Diff line Loading @@ -401,6 +401,23 @@ public final class MotionEvent extends InputEvent implements Parcelable { */ public static final int FLAG_TAINTED = 0x80000000; /** * Private flag indicating that this event was synthesized by the system and * should be delivered to the accessibility focused view first. When being * dispatched such an event is not handled by predecessors of the accessibility * focused view and after the event reaches that view the flag is cleared and * normal event dispatch is performed. This ensures that the platform can click * on any view that has accessibility focus which is semantically equivalent to * asking the view to perform a click accessibility action but more generic as * views not implementing click action correctly can still be activated. * * @hide * @see #isTargetAccessibilityFocus() * @see #setTargetAccessibilityFocus(boolean) */ public static final int FLAG_TARGET_ACCESSIBILITY_FOCUS = 0x40000000; /** * Flag indicating the motion event intersected the top edge of the screen. */ Loading Loading @@ -1766,6 +1783,20 @@ public final class MotionEvent extends InputEvent implements Parcelable { nativeSetFlags(mNativePtr, tainted ? flags | FLAG_TAINTED : flags & ~FLAG_TAINTED); } /** @hide */ public final boolean isTargetAccessibilityFocus() { final int flags = getFlags(); return (flags & FLAG_TARGET_ACCESSIBILITY_FOCUS) != 0; } /** @hide */ public final void setTargetAccessibilityFocus(boolean targetsFocus) { final int flags = getFlags(); nativeSetFlags(mNativePtr, targetsFocus ? flags | FLAG_TARGET_ACCESSIBILITY_FOCUS : flags & ~FLAG_TARGET_ACCESSIBILITY_FOCUS); } /** * Returns the time (in ms) when the user originally pressed down to start * a stream of position events. Loading core/java/android/view/View.java +31 −138 Original line number Diff line number Diff line Loading @@ -5553,12 +5553,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** * Gets the location of this view in screen coordintates. * Gets the location of this view in screen coordinates. * * @param outRect The output location * @hide */ public void getBoundsOnScreen(Rect outRect) { getBoundsOnScreen(outRect, false); } /** * Gets the location of this view in screen coordinates. * * @param outRect The output location * @param clipToParent Whether to clip child bounds to the parent ones. * @hide */ public void getBoundsOnScreen(Rect outRect, boolean clipToParent) { if (mAttachInfo == null) { return; } Loading @@ -5578,6 +5589,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, position.offset(-parentView.mScrollX, -parentView.mScrollY); if (clipToParent) { position.left = Math.max(position.left, 0); position.top = Math.max(position.top, 0); position.right = Math.min(position.right, parentView.getWidth()); position.bottom = Math.min(position.bottom, parentView.getHeight()); } if (!parentView.hasIdentityMatrix()) { parentView.getMatrix().mapRect(position); } Loading Loading @@ -5609,7 +5627,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, getDrawingRect(bounds); info.setBoundsInParent(bounds); getBoundsOnScreen(bounds); getBoundsOnScreen(bounds, true); info.setBoundsInScreen(bounds); ViewParent parent = getParentForAccessibility(); Loading Loading @@ -5804,142 +5822,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return false; } /** * Computes a point on which a sequence of a down/up event can be sent to * trigger clicking this view. This method is for the exclusive use by the * accessibility layer to determine where to send a click event in explore * by touch mode. * * @param interactiveRegion The interactive portion of this window. * @param outPoint The point to populate. * @return True of such a point exists. */ boolean computeClickPointInScreenForAccessibility(Region interactiveRegion, Point outPoint) { // Since the interactive portion of the view is a region but as a view // may have a transformation matrix which cannot be applied to a // region we compute the view bounds rectangle and all interactive // predecessor's and sibling's (siblings of predecessors included) // rectangles that intersect the view bounds. At the // end if the view was partially covered by another interactive // view we compute the view's interactive region and pick a point // on its boundary path as regions do not offer APIs to get inner // points. Note that the the code is optimized to fail early and // avoid unnecessary allocations plus computations. // The current approach has edge cases that may produce false // positives or false negatives. For example, a portion of the // view may be covered by an interactive descendant of a // predecessor, which we do not compute. Also a view may be handling // raw touch events instead registering click listeners, which // we cannot compute. Despite these limitations this approach will // work most of the time and it is a huge improvement over just // blindly sending the down and up events in the center of the // view. // Cannot click on an unattached view. if (mAttachInfo == null) { return false; } // Attached to an invisible window means this view is not visible. if (mAttachInfo.mWindowVisibility != View.VISIBLE) { return false; } RectF bounds = mAttachInfo.mTmpTransformRect; bounds.set(0, 0, getWidth(), getHeight()); List<RectF> intersections = mAttachInfo.mTmpRectList; intersections.clear(); if (mParent instanceof ViewGroup) { ViewGroup parentGroup = (ViewGroup) mParent; if (!parentGroup.translateBoundsAndIntersectionsInWindowCoordinates( this, bounds, intersections)) { intersections.clear(); return false; } } // Take into account the window location. final int dx = mAttachInfo.mWindowLeft; final int dy = mAttachInfo.mWindowTop; bounds.offset(dx, dy); offsetRects(intersections, dx, dy); if (intersections.isEmpty() && interactiveRegion == null) { outPoint.set((int) bounds.centerX(), (int) bounds.centerY()); } else { // This view is partially covered by other views, then compute // the not covered region and pick a point on its boundary. Region region = new Region(); region.set((int) bounds.left, (int) bounds.top, (int) bounds.right, (int) bounds.bottom); final int intersectionCount = intersections.size(); for (int i = intersectionCount - 1; i >= 0; i--) { RectF intersection = intersections.remove(i); region.op((int) intersection.left, (int) intersection.top, (int) intersection.right, (int) intersection.bottom, Region.Op.DIFFERENCE); } // If the view is completely covered, done. if (region.isEmpty()) { return false; } // Take into account the interactive portion of the window // as the rest is covered by other windows. If no such a region // then the whole window is interactive. if (interactiveRegion != null) { region.op(interactiveRegion, Region.Op.INTERSECT); } // Take into account the window bounds. final View root = getRootView(); if (root != null) { region.op(dx, dy, root.getWidth() + dx, root.getHeight() + dy, Region.Op.INTERSECT); } // If the view is completely covered, done. if (region.isEmpty()) { return false; } // Try a shortcut here. if (region.isRect()) { Rect regionBounds = mAttachInfo.mTmpInvalRect; region.getBounds(regionBounds); outPoint.set(regionBounds.centerX(), regionBounds.centerY()); return true; } // Get the a point on the region boundary path. Path path = region.getBoundaryPath(); PathMeasure pathMeasure = new PathMeasure(path, false); final float[] coordinates = mAttachInfo.mTmpTransformLocation; // Without loss of generality pick a point. final float point = pathMeasure.getLength() * 0.01f; if (!pathMeasure.getPosTan(point, coordinates, null)) { return false; } outPoint.set(Math.round(coordinates[0]), Math.round(coordinates[1])); } return true; } static void offsetRects(List<RectF> rects, float offsetX, float offsetY) { final int rectCount = rects.size(); for (int i = 0; i < rectCount; i++) { RectF intersection = rects.get(i); intersection.offset(offsetX, offsetY); } } /** * Returns the delegate for implementing accessibility support via * composition. For more details see {@link AccessibilityDelegate}. Loading Loading @@ -8555,6 +8437,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return True if the event was handled by the view, false otherwise. */ public boolean dispatchTouchEvent(MotionEvent event) { // If the event should be handled by accessibility focus first. if (event.isTargetAccessibilityFocus()) { // We don't have focus or no virtual descendant has it, do not handle the event. if (!isAccessibilityFocused() && !(getViewRootImpl() != null && getViewRootImpl() .getAccessibilityFocusedHost() == this)) { return false; } // We have focus and got the event, then use normal event dispatch. event.setTargetAccessibilityFocus(false); } boolean result = false; if (mInputEventConsistencyVerifier != null) { Loading core/java/android/view/ViewGroup.java +20 −205 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl +0 −4 Original line number Diff line number Diff line Loading @@ -54,10 +54,6 @@ interface IAccessibilityServiceConnection { int action, in Bundle arguments, int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId); boolean computeClickPointInScreen(int accessibilityWindowId, long accessibilityNodeId, int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId); AccessibilityWindowInfo getWindow(int windowId); List<AccessibilityWindowInfo> getWindows(); Loading
core/java/android/view/AccessibilityInteractionController.java +0 −95 Original line number Diff line number Diff line Loading @@ -636,95 +636,6 @@ final class AccessibilityInteractionController { } } public void computeClickPointInScreenClientThread(long accessibilityNodeId, Region interactiveRegion, int interactionId, IAccessibilityInteractionConnectionCallback callback, int interrogatingPid, long interrogatingTid, MagnificationSpec spec) { Message message = mHandler.obtainMessage(); message.what = PrivateHandler.MSG_COMPUTE_CLICK_POINT_IN_SCREEN; SomeArgs args = SomeArgs.obtain(); args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId); args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId); args.argi3 = interactionId; args.arg1 = callback; args.arg2 = spec; args.arg3 = interactiveRegion; message.obj = args; // If the interrogation is performed by the same thread as the main UI // thread in this process, set the message as a static reference so // after this call completes the same thread but in the interrogating // client can handle the message to generate the result. if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) { AccessibilityInteractionClient.getInstanceForThread( interrogatingTid).setSameThreadMessage(message); } else { mHandler.sendMessage(message); } } private void computeClickPointInScreenUiThread(Message message) { SomeArgs args = (SomeArgs) message.obj; final int accessibilityViewId = args.argi1; final int virtualDescendantId = args.argi2; final int interactionId = args.argi3; final IAccessibilityInteractionConnectionCallback callback = (IAccessibilityInteractionConnectionCallback) args.arg1; final MagnificationSpec spec = (MagnificationSpec) args.arg2; final Region interactiveRegion = (Region) args.arg3; args.recycle(); boolean succeeded = false; Point point = mTempPoint; try { if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) { return; } View target = null; if (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { target = findViewByAccessibilityId(accessibilityViewId); } else { target = mViewRootImpl.mView; } if (target != null && isShown(target)) { AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider(); if (provider != null) { // For virtual views just use the center of the bounds in screen. AccessibilityNodeInfo node = null; if (virtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { node = provider.createAccessibilityNodeInfo(virtualDescendantId); } else { node = provider.createAccessibilityNodeInfo( AccessibilityNodeProvider.HOST_VIEW_ID); } if (node != null) { succeeded = true; Rect boundsInScreen = mTempRect; node.getBoundsInScreen(boundsInScreen); point.set(boundsInScreen.centerX(), boundsInScreen.centerY()); } } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { // For a real view, ask the view to compute the click point. succeeded = target.computeClickPointInScreenForAccessibility( interactiveRegion, point); } } } finally { try { Point result = null; if (succeeded) { applyAppScaleAndMagnificationSpecIfNeeded(point, spec); result = point; } callback.setComputeClickPointInScreenActionResult(result, interactionId); } catch (RemoteException re) { /* ignore - the other side will time out */ } } } private View findViewByAccessibilityId(int accessibilityId) { View root = mViewRootImpl.mView; if (root == null) { Loading Loading @@ -1201,7 +1112,6 @@ final class AccessibilityInteractionController { private final static int MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT = 4; private final static int MSG_FIND_FOCUS = 5; private final static int MSG_FOCUS_SEARCH = 6; private final static int MSG_COMPUTE_CLICK_POINT_IN_SCREEN = 7; public PrivateHandler(Looper looper) { super(looper); Loading @@ -1223,8 +1133,6 @@ final class AccessibilityInteractionController { return "MSG_FIND_FOCUS"; case MSG_FOCUS_SEARCH: return "MSG_FOCUS_SEARCH"; case MSG_COMPUTE_CLICK_POINT_IN_SCREEN: return "MSG_COMPUTE_CLICK_POINT_IN_SCREEN"; default: throw new IllegalArgumentException("Unknown message type: " + type); } Loading Loading @@ -1252,9 +1160,6 @@ final class AccessibilityInteractionController { case MSG_FOCUS_SEARCH: { focusSearchUiThread(message); } break; case MSG_COMPUTE_CLICK_POINT_IN_SCREEN: { computeClickPointInScreenUiThread(message); } break; default: throw new IllegalArgumentException("Unknown message type: " + type); } Loading
core/java/android/view/MotionEvent.java +31 −0 Original line number Diff line number Diff line Loading @@ -401,6 +401,23 @@ public final class MotionEvent extends InputEvent implements Parcelable { */ public static final int FLAG_TAINTED = 0x80000000; /** * Private flag indicating that this event was synthesized by the system and * should be delivered to the accessibility focused view first. When being * dispatched such an event is not handled by predecessors of the accessibility * focused view and after the event reaches that view the flag is cleared and * normal event dispatch is performed. This ensures that the platform can click * on any view that has accessibility focus which is semantically equivalent to * asking the view to perform a click accessibility action but more generic as * views not implementing click action correctly can still be activated. * * @hide * @see #isTargetAccessibilityFocus() * @see #setTargetAccessibilityFocus(boolean) */ public static final int FLAG_TARGET_ACCESSIBILITY_FOCUS = 0x40000000; /** * Flag indicating the motion event intersected the top edge of the screen. */ Loading Loading @@ -1766,6 +1783,20 @@ public final class MotionEvent extends InputEvent implements Parcelable { nativeSetFlags(mNativePtr, tainted ? flags | FLAG_TAINTED : flags & ~FLAG_TAINTED); } /** @hide */ public final boolean isTargetAccessibilityFocus() { final int flags = getFlags(); return (flags & FLAG_TARGET_ACCESSIBILITY_FOCUS) != 0; } /** @hide */ public final void setTargetAccessibilityFocus(boolean targetsFocus) { final int flags = getFlags(); nativeSetFlags(mNativePtr, targetsFocus ? flags | FLAG_TARGET_ACCESSIBILITY_FOCUS : flags & ~FLAG_TARGET_ACCESSIBILITY_FOCUS); } /** * Returns the time (in ms) when the user originally pressed down to start * a stream of position events. Loading
core/java/android/view/View.java +31 −138 Original line number Diff line number Diff line Loading @@ -5553,12 +5553,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** * Gets the location of this view in screen coordintates. * Gets the location of this view in screen coordinates. * * @param outRect The output location * @hide */ public void getBoundsOnScreen(Rect outRect) { getBoundsOnScreen(outRect, false); } /** * Gets the location of this view in screen coordinates. * * @param outRect The output location * @param clipToParent Whether to clip child bounds to the parent ones. * @hide */ public void getBoundsOnScreen(Rect outRect, boolean clipToParent) { if (mAttachInfo == null) { return; } Loading @@ -5578,6 +5589,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, position.offset(-parentView.mScrollX, -parentView.mScrollY); if (clipToParent) { position.left = Math.max(position.left, 0); position.top = Math.max(position.top, 0); position.right = Math.min(position.right, parentView.getWidth()); position.bottom = Math.min(position.bottom, parentView.getHeight()); } if (!parentView.hasIdentityMatrix()) { parentView.getMatrix().mapRect(position); } Loading Loading @@ -5609,7 +5627,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, getDrawingRect(bounds); info.setBoundsInParent(bounds); getBoundsOnScreen(bounds); getBoundsOnScreen(bounds, true); info.setBoundsInScreen(bounds); ViewParent parent = getParentForAccessibility(); Loading Loading @@ -5804,142 +5822,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return false; } /** * Computes a point on which a sequence of a down/up event can be sent to * trigger clicking this view. This method is for the exclusive use by the * accessibility layer to determine where to send a click event in explore * by touch mode. * * @param interactiveRegion The interactive portion of this window. * @param outPoint The point to populate. * @return True of such a point exists. */ boolean computeClickPointInScreenForAccessibility(Region interactiveRegion, Point outPoint) { // Since the interactive portion of the view is a region but as a view // may have a transformation matrix which cannot be applied to a // region we compute the view bounds rectangle and all interactive // predecessor's and sibling's (siblings of predecessors included) // rectangles that intersect the view bounds. At the // end if the view was partially covered by another interactive // view we compute the view's interactive region and pick a point // on its boundary path as regions do not offer APIs to get inner // points. Note that the the code is optimized to fail early and // avoid unnecessary allocations plus computations. // The current approach has edge cases that may produce false // positives or false negatives. For example, a portion of the // view may be covered by an interactive descendant of a // predecessor, which we do not compute. Also a view may be handling // raw touch events instead registering click listeners, which // we cannot compute. Despite these limitations this approach will // work most of the time and it is a huge improvement over just // blindly sending the down and up events in the center of the // view. // Cannot click on an unattached view. if (mAttachInfo == null) { return false; } // Attached to an invisible window means this view is not visible. if (mAttachInfo.mWindowVisibility != View.VISIBLE) { return false; } RectF bounds = mAttachInfo.mTmpTransformRect; bounds.set(0, 0, getWidth(), getHeight()); List<RectF> intersections = mAttachInfo.mTmpRectList; intersections.clear(); if (mParent instanceof ViewGroup) { ViewGroup parentGroup = (ViewGroup) mParent; if (!parentGroup.translateBoundsAndIntersectionsInWindowCoordinates( this, bounds, intersections)) { intersections.clear(); return false; } } // Take into account the window location. final int dx = mAttachInfo.mWindowLeft; final int dy = mAttachInfo.mWindowTop; bounds.offset(dx, dy); offsetRects(intersections, dx, dy); if (intersections.isEmpty() && interactiveRegion == null) { outPoint.set((int) bounds.centerX(), (int) bounds.centerY()); } else { // This view is partially covered by other views, then compute // the not covered region and pick a point on its boundary. Region region = new Region(); region.set((int) bounds.left, (int) bounds.top, (int) bounds.right, (int) bounds.bottom); final int intersectionCount = intersections.size(); for (int i = intersectionCount - 1; i >= 0; i--) { RectF intersection = intersections.remove(i); region.op((int) intersection.left, (int) intersection.top, (int) intersection.right, (int) intersection.bottom, Region.Op.DIFFERENCE); } // If the view is completely covered, done. if (region.isEmpty()) { return false; } // Take into account the interactive portion of the window // as the rest is covered by other windows. If no such a region // then the whole window is interactive. if (interactiveRegion != null) { region.op(interactiveRegion, Region.Op.INTERSECT); } // Take into account the window bounds. final View root = getRootView(); if (root != null) { region.op(dx, dy, root.getWidth() + dx, root.getHeight() + dy, Region.Op.INTERSECT); } // If the view is completely covered, done. if (region.isEmpty()) { return false; } // Try a shortcut here. if (region.isRect()) { Rect regionBounds = mAttachInfo.mTmpInvalRect; region.getBounds(regionBounds); outPoint.set(regionBounds.centerX(), regionBounds.centerY()); return true; } // Get the a point on the region boundary path. Path path = region.getBoundaryPath(); PathMeasure pathMeasure = new PathMeasure(path, false); final float[] coordinates = mAttachInfo.mTmpTransformLocation; // Without loss of generality pick a point. final float point = pathMeasure.getLength() * 0.01f; if (!pathMeasure.getPosTan(point, coordinates, null)) { return false; } outPoint.set(Math.round(coordinates[0]), Math.round(coordinates[1])); } return true; } static void offsetRects(List<RectF> rects, float offsetX, float offsetY) { final int rectCount = rects.size(); for (int i = 0; i < rectCount; i++) { RectF intersection = rects.get(i); intersection.offset(offsetX, offsetY); } } /** * Returns the delegate for implementing accessibility support via * composition. For more details see {@link AccessibilityDelegate}. Loading Loading @@ -8555,6 +8437,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return True if the event was handled by the view, false otherwise. */ public boolean dispatchTouchEvent(MotionEvent event) { // If the event should be handled by accessibility focus first. if (event.isTargetAccessibilityFocus()) { // We don't have focus or no virtual descendant has it, do not handle the event. if (!isAccessibilityFocused() && !(getViewRootImpl() != null && getViewRootImpl() .getAccessibilityFocusedHost() == this)) { return false; } // We have focus and got the event, then use normal event dispatch. event.setTargetAccessibilityFocus(false); } boolean result = false; if (mInputEventConsistencyVerifier != null) { Loading
core/java/android/view/ViewGroup.java +20 −205 File changed.Preview size limit exceeded, changes collapsed. Show changes