Index: views/widget/native_widget_win.cc |
=================================================================== |
--- views/widget/native_widget_win.cc (revision 107097) |
+++ views/widget/native_widget_win.cc (working copy) |
@@ -380,8 +380,6 @@ |
ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET), |
can_update_layered_window_(true), |
restore_focus_when_enabled_(false), |
- accessibility_view_events_index_(-1), |
- accessibility_view_events_(kMaxAccessibilityViewEvents), |
previous_cursor_(NULL), |
fullscreen_(false), |
force_hidden_count_(0), |
@@ -447,31 +445,12 @@ |
SetInitialFocus(); |
} |
-View* NativeWidgetWin::GetAccessibilityViewEventAt(int id) { |
- // Convert from MSAA child id. |
- id = -(id + 1); |
- DCHECK(id >= 0 && id < kMaxAccessibilityViewEvents); |
- return accessibility_view_events_[id]; |
+View* NativeWidgetWin::GetViewByAccessibleId(long child_id) { |
+ // The IAccessible2 unique ID is the negation of the child ID; |
+ // see the comments in SendNativeAccessibilityEvent for details. |
+ return FindViewByIA2UniqueId(-child_id, GetWidget()->GetRootView()); |
} |
-int NativeWidgetWin::AddAccessibilityViewEvent(View* view) { |
- accessibility_view_events_index_ = |
- (accessibility_view_events_index_ + 1) % kMaxAccessibilityViewEvents; |
- accessibility_view_events_[accessibility_view_events_index_] = view; |
- |
- // Convert to MSAA child id. |
- return -(accessibility_view_events_index_ + 1); |
-} |
- |
-void NativeWidgetWin::ClearAccessibilityViewEvent(View* view) { |
- for (std::vector<View*>::iterator it = accessibility_view_events_.begin(); |
- it != accessibility_view_events_.end(); |
- ++it) { |
- if (*it == view) |
- *it = NULL; |
- } |
-} |
- |
void NativeWidgetWin::PushForceHidden() { |
if (force_hidden_count_++ == 0) |
Hide(); |
@@ -591,8 +570,6 @@ |
void NativeWidgetWin::ViewRemoved(View* view) { |
if (drop_target_.get()) |
drop_target_->ResetTargetViewIfEquals(view); |
- |
- ClearAccessibilityViewEvent(view); |
} |
void NativeWidgetWin::SetNativeWindowProperty(const char* name, void* value) { |
@@ -623,14 +600,32 @@ |
void NativeWidgetWin::SendNativeAccessibilityEvent( |
View* view, |
ui::AccessibilityTypes::Event event_type) { |
- // Now call the Windows-specific method to notify MSAA clients of this |
- // event. The widget gives us a temporary unique child ID to associate |
- // with this view so that clients can call get_accChild in |
- // NativeViewAccessibilityWin to retrieve the IAccessible associated |
- // with this view. |
- int child_id = AddAccessibilityViewEvent(view); |
- ::NotifyWinEvent(NativeViewAccessibilityWin::MSAAEvent(event_type), |
- GetNativeView(), OBJID_CLIENT, child_id); |
+ DWORD native_event = NativeViewAccessibilityWin::MSAAEvent(event_type); |
+ gfx::NativeView native_view = this->GetNativeView(); |
+ |
+ // Get the unique ID from the view's IAccessible2 interface. |
+ IAccessible* accessible = view->GetNativeViewAccessible(); |
+ IAccessible2* accessible2 = NULL; |
+ HRESULT hr = accessible->QueryInterface( |
+ IID_IAccessible2, reinterpret_cast<void**>(&accessible2)); |
+ if (hr != S_OK) { |
+ // If this is reached, you're probably trying to fire a notification on a |
+ // views::NativeViewHost that has only a default IAccessible. You have to |
+ // either call ::NotifyWinEvent directly, or override |
+ // GetNativeViewAccessible for that view. |
+ NOTREACHED(); |
+ return; |
+ } |
+ long unique_id; |
+ hr = accessible2->get_uniqueID(&unique_id); |
+ DCHECK_EQ(hr, S_OK); |
+ |
+ // Send the negation of the unique id as the child id parameter to |
+ // NotifyWinEvent. The client will call get_accChild on the top-level |
+ // NativeViewAccessibilityWin object, where positive child ids are |
+ // interpreted as 1-based child indices, and negative child ids are |
+ // interpreted as unique ids. |
+ ::NotifyWinEvent(native_event, native_view, OBJID_CLIENT, -unique_id); |
} |
void NativeWidgetWin::SetMouseCapture() { |
@@ -2465,6 +2460,25 @@ |
SetMsgHandled(delegate_->OnKeyEvent(key)); |
} |
+View* NativeWidgetWin::FindViewByIA2UniqueId(long id, View* view) { |
+ IAccessible* accessible = view->GetNativeViewAccessible(); |
+ IAccessible2* accessible2 = NULL; |
+ if (S_OK == accessible->QueryInterface( |
+ IID_IAccessible2, reinterpret_cast<void**>(&accessible2))) { |
+ long unique_id; |
+ if (S_OK == accessible2->get_uniqueID(&unique_id) && id == unique_id) |
+ return view; |
+ } |
+ |
+ for (int i = 0; i < view->child_count(); i++) { |
+ View* result = FindViewByIA2UniqueId(id, view->child_at(i)); |
+ if (result) |
+ return result; |
+ } |
+ |
+ return NULL; |
+} |
+ |
//////////////////////////////////////////////////////////////////////////////// |
// Widget, public: |