1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file.
4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochpackage org.chromium.content.browser.accessibility;
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport android.content.Context;
8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport android.graphics.Rect;
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport android.os.Bundle;
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport android.os.Build;
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport android.view.MotionEvent;
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport android.view.View;
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport android.view.accessibility.AccessibilityEvent;
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport android.view.accessibility.AccessibilityManager;
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport android.view.accessibility.AccessibilityNodeInfo;
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport android.view.accessibility.AccessibilityNodeProvider;
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport android.view.inputmethod.InputMethodManager;
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport org.chromium.base.CalledByNative;
20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport org.chromium.base.JNINamespace;
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport org.chromium.content.browser.ContentViewCore;
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport org.chromium.content.browser.RenderCoordinates;
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport java.util.ArrayList;
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport java.util.List;
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/**
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * Native accessibility for a {@link ContentViewCore}.
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *
30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * This class is safe to load on ICS and can be used to run tests, but
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * only the subclass, JellyBeanBrowserAccessibilityManager, actually
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * has a AccessibilityNodeProvider implementation needed for native
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * accessibility.
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch */
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch@JNINamespace("content")
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochpublic class BrowserAccessibilityManager {
379ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    private static final String TAG = "BrowserAccessibilityManager";
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private ContentViewCore mContentViewCore;
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private AccessibilityManager mAccessibilityManager;
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private RenderCoordinates mRenderCoordinates;
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private int mNativeObj;
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private int mAccessibilityFocusId;
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private int mCurrentHoverId;
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private final int[] mTempLocation = new int[2];
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private View mView;
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private boolean mUserHasTouchExplored;
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private boolean mFrameInfoInitialized;
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // If this is true, enables an experimental feature that focuses the web page after it
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // finishes loading. Disabled for now because it can be confusing if the user was
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // trying to do something when this happens.
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private boolean mFocusPageOnLoad;
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    /**
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     * Create a BrowserAccessibilityManager object, which is owned by the C++
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     * BrowserAccessibilityManagerAndroid instance, and connects to the content view.
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     * @param nativeBrowserAccessibilityManagerAndroid A pointer to the counterpart native
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     *     C++ object that owns this object.
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     * @param contentViewCore The content view that this object provides accessibility for.
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     */
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private static BrowserAccessibilityManager create(int nativeBrowserAccessibilityManagerAndroid,
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            ContentViewCore contentViewCore) {
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            return new JellyBeanBrowserAccessibilityManager(
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    nativeBrowserAccessibilityManagerAndroid, contentViewCore);
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        } else {
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            return new BrowserAccessibilityManager(
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    nativeBrowserAccessibilityManagerAndroid, contentViewCore);
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    protected BrowserAccessibilityManager(int nativeBrowserAccessibilityManagerAndroid,
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            ContentViewCore contentViewCore) {
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mNativeObj = nativeBrowserAccessibilityManagerAndroid;
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mContentViewCore = contentViewCore;
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mContentViewCore.setBrowserAccessibilityManager(this);
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mAccessibilityFocusId = View.NO_ID;
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mCurrentHoverId = View.NO_ID;
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mView = mContentViewCore.getContainerView();
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mRenderCoordinates = mContentViewCore.getRenderCoordinates();
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mAccessibilityManager =
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            (AccessibilityManager) mContentViewCore.getContext()
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            .getSystemService(Context.ACCESSIBILITY_SERVICE);
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void onNativeObjectDestroyed() {
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (mContentViewCore.getBrowserAccessibilityManager() == this) {
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            mContentViewCore.setBrowserAccessibilityManager(null);
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mNativeObj = 0;
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mContentViewCore = null;
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    /**
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     * @return An AccessibilityNodeProvider on JellyBean, and null on previous versions.
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     */
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return null;
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    /**
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     * @see AccessibilityNodeProvider#createAccessibilityNodeInfo(int)
106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     */
107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    protected AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (!mAccessibilityManager.isEnabled() || mNativeObj == 0 || !mFrameInfoInitialized) {
109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            return null;
110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        int rootId = nativeGetRootId(mNativeObj);
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (virtualViewId == View.NO_ID) {
114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            virtualViewId = rootId;
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (mAccessibilityFocusId == View.NO_ID) {
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            mAccessibilityFocusId = rootId;
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        final AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(mView);
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        info.setPackageName(mContentViewCore.getContext().getPackageName());
122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        info.setSource(mView, virtualViewId);
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (nativePopulateAccessibilityNodeInfo(mNativeObj, info, virtualViewId)) {
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            return info;
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        } else {
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            return null;
128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    /**
132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     * @see AccessibilityNodeProvider#findAccessibilityNodeInfosByText(String, int)
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     */
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    protected List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text,
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            int virtualViewId) {
136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return new ArrayList<AccessibilityNodeInfo>();
137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    /**
140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     * @see AccessibilityNodeProvider#performAction(int, int, Bundle)
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     */
142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    protected boolean performAction(int virtualViewId, int action, Bundle arguments) {
143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (!mAccessibilityManager.isEnabled() || mNativeObj == 0) {
144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            return false;
145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        switch (action) {
148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS:
149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                if (mAccessibilityFocusId == virtualViewId) {
150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    return true;
151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                }
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                mAccessibilityFocusId = virtualViewId;
154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                sendAccessibilityEvent(mAccessibilityFocusId,
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                return true;
157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS:
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                if (mAccessibilityFocusId == virtualViewId) {
159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    mAccessibilityFocusId = View.NO_ID;
160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                }
161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                return true;
162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            case AccessibilityNodeInfo.ACTION_CLICK:
163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                nativeClick(mNativeObj, virtualViewId);
164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                break;
165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            case AccessibilityNodeInfo.ACTION_FOCUS:
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                nativeFocus(mNativeObj, virtualViewId);
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                break;
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS:
169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                nativeBlur(mNativeObj);
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                break;
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            default:
172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                break;
173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return false;
175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    /**
178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     * @see View#onHoverEvent(MotionEvent)
179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     */
180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    public boolean onHoverEvent(MotionEvent event) {
181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (!mAccessibilityManager.isEnabled() || mNativeObj == 0) {
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            return false;
183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (event.getAction() == MotionEvent.ACTION_HOVER_EXIT) return true;
186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mUserHasTouchExplored = true;
188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        float x = event.getX();
189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        float y = event.getY();
190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Convert to CSS coordinates.
192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        int cssX = (int) (mRenderCoordinates.fromPixToLocalCss(x) +
193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          mRenderCoordinates.getScrollX());
194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        int cssY = (int) (mRenderCoordinates.fromPixToLocalCss(y) +
195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          mRenderCoordinates.getScrollY());
196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        int id = nativeHitTest(mNativeObj, cssX, cssY);
197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (mCurrentHoverId != id) {
198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            sendAccessibilityEvent(mCurrentHoverId, AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            mCurrentHoverId = id;
201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return true;
204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    /**
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     * Called by ContentViewCore to notify us when the frame info is initialized,
208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     * the first time, since until that point, we can't use mRenderCoordinates to transform
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     * web coordinates to screen coordinates.
210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     */
211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    public void notifyFrameInfoInitialized() {
212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (mFrameInfoInitialized) return;
213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mFrameInfoInitialized = true;
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // (Re-) focus focused element, since we weren't able to create an
216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // AccessibilityNodeInfo for this element before.
217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (mAccessibilityFocusId != View.NO_ID) {
218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            sendAccessibilityEvent(mAccessibilityFocusId,
219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void sendAccessibilityEvent(int virtualViewId, int eventType) {
224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (!mAccessibilityManager.isEnabled() || mNativeObj == 0) return;
225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setPackageName(mContentViewCore.getContext().getPackageName());
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        int rootId = nativeGetRootId(mNativeObj);
229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (virtualViewId == rootId) {
230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            virtualViewId = View.NO_ID;
231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setSource(mView, virtualViewId);
233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (!nativePopulateAccessibilityEvent(mNativeObj, event, virtualViewId, eventType)) return;
234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // This is currently needed if we want Android to draw the yellow box around
236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // the item that has accessibility focus. In practice, this doesn't seem to slow
237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // things down, because it's only called when the accessibility focus moves.
238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // TODO(dmazzoni): remove this if/when Android framework fixes bug.
239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mContentViewCore.getContainerView().postInvalidate();
240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mContentViewCore.getContainerView().requestSendAccessibilityEvent(mView, event);
242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void handlePageLoaded(int id) {
246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (mUserHasTouchExplored) return;
247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (mFocusPageOnLoad) {
249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            // Focus the natively focused node (usually document),
250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            // if this feature is enabled.
251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            mAccessibilityFocusId = id;
252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_FOCUSED);
253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void handleFocusChanged(int id) {
258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (mAccessibilityFocusId == id) return;
259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mAccessibilityFocusId = id;
261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_FOCUSED);
262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void handleCheckStateChanged(int id) {
266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_CLICKED);
267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void handleTextSelectionChanged(int id) {
271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void handleEditableTextChanged(int id) {
276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void handleContentChanged(int id) {
281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        sendAccessibilityEvent(id, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void handleNavigate() {
286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mAccessibilityFocusId = View.NO_ID;
287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mUserHasTouchExplored = false;
288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mFrameInfoInitialized = false;
289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void handleScrolledToAnchor(int id) {
293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (mAccessibilityFocusId == id) {
294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            return;
295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mAccessibilityFocusId = id;
298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void announceLiveRegionText(String text) {
303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mView.announceForAccessibility(text);
304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void setAccessibilityNodeInfoParent(AccessibilityNodeInfo node, int parentId) {
308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        node.setParent(mView, parentId);
309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void addAccessibilityNodeInfoChild(AccessibilityNodeInfo node, int child_id) {
313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        node.addChild(mView, child_id);
314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void setAccessibilityNodeInfoBooleanAttributes(AccessibilityNodeInfo node,
318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            int virtualViewId, boolean checkable, boolean checked, boolean clickable,
319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            boolean enabled, boolean focusable, boolean focused, boolean password,
320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            boolean scrollable, boolean selected, boolean visibleToUser) {
321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        node.setCheckable(checkable);
322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        node.setChecked(checked);
323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        node.setClickable(clickable);
324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        node.setEnabled(enabled);
325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        node.setFocusable(focusable);
326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        node.setFocused(focused);
327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        node.setPassword(password);
328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        node.setScrollable(scrollable);
329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        node.setSelected(selected);
330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        node.setVisibleToUser(visibleToUser);
331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (focusable) {
333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            if (focused) {
334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                node.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            } else {
336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                node.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            }
338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (mAccessibilityFocusId == virtualViewId) {
341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            node.setAccessibilityFocused(true);
342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            node.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        } else {
344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            node.setAccessibilityFocused(false);
345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            node.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (clickable) {
349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            node.addAction(AccessibilityNodeInfo.ACTION_CLICK);
350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void setAccessibilityNodeInfoStringAttributes(AccessibilityNodeInfo node,
355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            String className, String contentDescription) {
356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        node.setClassName(className);
357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        node.setContentDescription(contentDescription);
358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void setAccessibilityNodeInfoLocation(AccessibilityNodeInfo node,
362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            int absoluteLeft, int absoluteTop, int parentRelativeLeft, int parentRelativeTop,
363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            int width, int height, boolean isRootNode) {
364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // First set the bounds in parent.
365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        Rect boundsInParent = new Rect(parentRelativeLeft, parentRelativeTop,
366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                parentRelativeLeft + width, parentRelativeTop + height);
367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (isRootNode) {
368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            // Offset of the web content relative to the View.
369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            boundsInParent.offset(0, (int) mRenderCoordinates.getContentOffsetYPix());
370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        node.setBoundsInParent(boundsInParent);
372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Now set the absolute rect, which requires several transformations.
374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        Rect rect = new Rect(absoluteLeft, absoluteTop, absoluteLeft + width, absoluteTop + height);
375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Offset by the scroll position.
377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        rect.offset(-(int) mRenderCoordinates.getScrollX(),
378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    -(int) mRenderCoordinates.getScrollY());
379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Convert CSS (web) pixels to Android View pixels
381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        rect.left = (int) mRenderCoordinates.fromLocalCssToPix(rect.left);
382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        rect.top = (int) mRenderCoordinates.fromLocalCssToPix(rect.top);
383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        rect.bottom = (int) mRenderCoordinates.fromLocalCssToPix(rect.bottom);
384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        rect.right = (int) mRenderCoordinates.fromLocalCssToPix(rect.right);
385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Offset by the location of the web content within the view.
387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        rect.offset(0,
388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    (int) mRenderCoordinates.getContentOffsetYPix());
389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Finally offset by the location of the view within the screen.
391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        final int[] viewLocation = new int[2];
392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        mView.getLocationOnScreen(viewLocation);
393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        rect.offset(viewLocation[0], viewLocation[1]);
394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        node.setBoundsInScreen(rect);
396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void setAccessibilityEventBooleanAttributes(AccessibilityEvent event,
400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            boolean checked, boolean enabled, boolean password, boolean scrollable) {
401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setChecked(checked);
402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setEnabled(enabled);
403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setPassword(password);
404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setScrollable(scrollable);
405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void setAccessibilityEventClassName(AccessibilityEvent event, String className) {
409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setClassName(className);
410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void setAccessibilityEventListAttributes(AccessibilityEvent event,
414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            int currentItemIndex, int itemCount) {
415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setCurrentItemIndex(currentItemIndex);
416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setItemCount(itemCount);
417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void setAccessibilityEventScrollAttributes(AccessibilityEvent event,
421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            int scrollX, int scrollY, int maxScrollX, int maxScrollY) {
422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setScrollX(scrollX);
423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setScrollY(scrollY);
424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setMaxScrollX(maxScrollX);
425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setMaxScrollY(maxScrollY);
426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void setAccessibilityEventTextChangedAttrs(AccessibilityEvent event,
430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            int fromIndex, int addedCount, int removedCount, String beforeText, String text) {
431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setFromIndex(fromIndex);
432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setAddedCount(addedCount);
433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setRemovedCount(removedCount);
434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setBeforeText(beforeText);
435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.getText().add(text);
436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    @CalledByNative
439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private void setAccessibilityEventSelectionAttrs(AccessibilityEvent event,
440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            int fromIndex, int addedCount, int itemCount, String text) {
441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setFromIndex(fromIndex);
442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setAddedCount(addedCount);
443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.setItemCount(itemCount);
444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        event.getText().add(text);
445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private native int nativeGetRootId(int nativeBrowserAccessibilityManagerAndroid);
448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private native int nativeHitTest(int nativeBrowserAccessibilityManagerAndroid, int x, int y);
449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private native boolean nativePopulateAccessibilityNodeInfo(
450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        int nativeBrowserAccessibilityManagerAndroid, AccessibilityNodeInfo info, int id);
451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private native boolean nativePopulateAccessibilityEvent(
452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        int nativeBrowserAccessibilityManagerAndroid, AccessibilityEvent event, int id,
453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        int eventType);
454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private native void nativeClick(int nativeBrowserAccessibilityManagerAndroid, int id);
455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private native void nativeFocus(int nativeBrowserAccessibilityManagerAndroid, int id);
456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    private native void nativeBlur(int nativeBrowserAccessibilityManagerAndroid);
457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
458