| Index: content/browser/accessibility/browser_accessibility_manager_win.cc
|
| diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc
|
| index 698f0190d22ce5fd700e3de92e71e435985be788..05ef1b139e53969fc66416ae3ea249bb99cec2c7 100644
|
| --- a/content/browser/accessibility/browser_accessibility_manager_win.cc
|
| +++ b/content/browser/accessibility/browser_accessibility_manager_win.cc
|
| @@ -73,22 +73,66 @@ IAccessible* BrowserAccessibilityManagerWin::GetParentIAccessible() {
|
| return delegate_->AccessibilityGetNativeViewAccessible();
|
| }
|
|
|
| -void BrowserAccessibilityManagerWin::MaybeCallNotifyWinEvent(DWORD event,
|
| - LONG child_id) {
|
| +void BrowserAccessibilityManagerWin::MaybeCallNotifyWinEvent(
|
| + DWORD event, BrowserAccessibility* node) {
|
| BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager();
|
| if (!delegate)
|
| return;
|
|
|
| + if (!node->IsNative())
|
| + return;
|
| +
|
| HWND hwnd = delegate->AccessibilityGetAcceleratedWidget();
|
| if (!hwnd)
|
| return;
|
|
|
| + // Inline text boxes are an internal implementation detail, we don't
|
| + // expose them to Windows.
|
| + if (node->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX)
|
| + return;
|
| +
|
| + // It doesn't make sense to fire a REORDER event on a leaf node; that
|
| + // happens when the node has internal children line inline text boxes.
|
| + if (event == EVENT_OBJECT_REORDER && node->PlatformIsLeaf())
|
| + return;
|
| +
|
| + // Don't fire focus, or load complete notifications if the
|
| + // window isn't focused, because that can confuse screen readers into
|
| + // entering their "browse" mode.
|
| + if ((event == EVENT_OBJECT_FOCUS ||
|
| + event == IA2_EVENT_DOCUMENT_LOAD_COMPLETE) &&
|
| + (!delegate_->AccessibilityViewHasFocus())) {
|
| + return;
|
| + }
|
| +
|
| + // NVDA gets confused if we focus the main document element when it hasn't
|
| + // finished loading and it has no children at all, so suppress that event.
|
| + if (event == EVENT_OBJECT_FOCUS &&
|
| + node == GetRoot() &&
|
| + node->PlatformChildCount() == 0 &&
|
| + !node->HasState(ui::AX_STATE_BUSY) &&
|
| + !node->GetBoolAttribute(ui::AX_ATTR_DOC_LOADED)) {
|
| + return;
|
| + }
|
| +
|
| + // If a focus event is needed on the root, fire that first before
|
| + // this event.
|
| + if (event == EVENT_OBJECT_FOCUS && node == GetRoot())
|
| + focus_event_on_root_needed_ = false;
|
| + else if (focus_event_on_root_needed_)
|
| + OnWindowFocused();
|
| +
|
| + LONG child_id = node->ToBrowserAccessibilityWin()->unique_id_win();
|
| ::NotifyWinEvent(event, hwnd, OBJID_CLIENT, child_id);
|
| }
|
|
|
| void BrowserAccessibilityManagerWin::OnNodeCreated(ui::AXNode* node) {
|
| BrowserAccessibilityManager::OnNodeCreated(node);
|
| BrowserAccessibility* obj = GetFromAXNode(node);
|
| + if (!obj)
|
| + return;
|
| + if (!obj->IsNative())
|
| + return;
|
| LONG unique_id_win = obj->ToBrowserAccessibilityWin()->unique_id_win();
|
| unique_id_to_ax_id_map_[unique_id_win] = obj->GetId();
|
| }
|
| @@ -98,6 +142,8 @@ void BrowserAccessibilityManagerWin::OnNodeWillBeDeleted(ui::AXNode* node) {
|
| BrowserAccessibility* obj = GetFromAXNode(node);
|
| if (!obj)
|
| return;
|
| + if (!obj->IsNative())
|
| + return;
|
| unique_id_to_ax_id_map_.erase(
|
| obj->ToBrowserAccessibilityWin()->unique_id_win());
|
| if (obj == tracked_scroll_object_) {
|
| @@ -173,9 +219,6 @@ void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
|
| case ui::AX_EVENT_ALERT:
|
| event_id = EVENT_SYSTEM_ALERT;
|
| break;
|
| - case ui::AX_EVENT_ARIA_ATTRIBUTE_CHANGED:
|
| - event_id = IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED;
|
| - break;
|
| case ui::AX_EVENT_AUTOCORRECTION_OCCURED:
|
| event_id = IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED;
|
| break;
|
| @@ -184,18 +227,12 @@ void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
|
| event_id = EVENT_OBJECT_FOCUS;
|
| node = GetRoot();
|
| break;
|
| - case ui::AX_EVENT_CHECKED_STATE_CHANGED:
|
| - event_id = EVENT_OBJECT_STATECHANGE;
|
| - break;
|
| case ui::AX_EVENT_CHILDREN_CHANGED:
|
| event_id = EVENT_OBJECT_REORDER;
|
| break;
|
| case ui::AX_EVENT_FOCUS:
|
| event_id = EVENT_OBJECT_FOCUS;
|
| break;
|
| - case ui::AX_EVENT_INVALID_STATUS_CHANGED:
|
| - event_id = EVENT_OBJECT_STATECHANGE;
|
| - break;
|
| case ui::AX_EVENT_LIVE_REGION_CHANGED:
|
| if (node->GetBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_BUSY))
|
| return;
|
| @@ -210,12 +247,6 @@ void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
|
| case ui::AX_EVENT_MENU_LIST_VALUE_CHANGED:
|
| event_id = EVENT_OBJECT_VALUECHANGE;
|
| break;
|
| - case ui::AX_EVENT_HIDE:
|
| - event_id = EVENT_OBJECT_HIDE;
|
| - break;
|
| - case ui::AX_EVENT_SHOW:
|
| - event_id = EVENT_OBJECT_SHOW;
|
| - break;
|
| case ui::AX_EVENT_SCROLL_POSITION_CHANGED:
|
| event_id = EVENT_SYSTEM_SCROLLINGEND;
|
| break;
|
| @@ -225,15 +256,9 @@ void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
|
| case ui::AX_EVENT_SELECTED_CHILDREN_CHANGED:
|
| event_id = EVENT_OBJECT_SELECTIONWITHIN;
|
| break;
|
| - case ui::AX_EVENT_TEXT_CHANGED:
|
| - event_id = EVENT_OBJECT_NAMECHANGE;
|
| - break;
|
| case ui::AX_EVENT_TEXT_SELECTION_CHANGED:
|
| event_id = IA2_EVENT_TEXT_CARET_MOVED;
|
| break;
|
| - case ui::AX_EVENT_VALUE_CHANGED:
|
| - event_id = EVENT_OBJECT_VALUECHANGE;
|
| - break;
|
| default:
|
| // Not all WebKit accessibility events result in a Windows
|
| // accessibility notification.
|
| @@ -245,8 +270,7 @@ void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
|
| // the AT client will then call get_accChild on the HWND's accessibility
|
| // object and pass it that same id, which we can use to retrieve the
|
| // IAccessible for this node.
|
| - LONG child_id = node->ToBrowserAccessibilityWin()->unique_id_win();
|
| - MaybeCallNotifyWinEvent(event_id, child_id);
|
| + MaybeCallNotifyWinEvent(event_id, node);
|
| }
|
|
|
| // If this is a layout complete notification (sent when a container scrolls)
|
| @@ -256,8 +280,7 @@ void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
|
| tracked_scroll_object_ &&
|
| tracked_scroll_object_->IsDescendantOf(node)) {
|
| MaybeCallNotifyWinEvent(
|
| - IA2_EVENT_VISIBLE_DATA_CHANGED,
|
| - tracked_scroll_object_->ToBrowserAccessibilityWin()->unique_id_win());
|
| + IA2_EVENT_VISIBLE_DATA_CHANGED, tracked_scroll_object_);
|
| tracked_scroll_object_->Release();
|
| tracked_scroll_object_ = NULL;
|
| }
|
| @@ -273,6 +296,19 @@ void BrowserAccessibilityManagerWin::OnAtomicUpdateFinished(
|
| // we need to fire a focus event on it.
|
| OnWindowFocused();
|
| }
|
| +
|
| + // BrowserAccessibilityManager::OnAtomicUpdateFinished calls
|
| + // OnUpdateFinished() on each node in |changes|. However, the
|
| + // IAccessibleText text for a node is a concatenatenation of all of its child
|
| + // text nodes, so we can't compute a node's IAccessibleText in
|
| + // OnUpdateFinished because its children may not have been updated yet.
|
| + //
|
| + // So we make a second pass here to update IAccessibleText.
|
| + for (size_t i = 0; i < changes.size(); ++i) {
|
| + BrowserAccessibility* obj = GetFromAXNode(changes[i].node);
|
| + if (obj && obj->IsNative())
|
| + obj->ToBrowserAccessibilityWin()->UpdateIAccessibleText();
|
| + }
|
| }
|
|
|
| void BrowserAccessibilityManagerWin::TrackScrollingObject(
|
| @@ -289,7 +325,7 @@ BrowserAccessibilityWin* BrowserAccessibilityManagerWin::GetFromUniqueIdWin(
|
| unique_id_to_ax_id_map_.find(unique_id_win);
|
| if (iter != unique_id_to_ax_id_map_.end()) {
|
| BrowserAccessibility* result = GetFromID(iter->second);
|
| - if (result)
|
| + if (result && result->IsNative())
|
| return result->ToBrowserAccessibilityWin();
|
| }
|
|
|
|
|