OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "views/accessibility/native_view_accessibility_win.h" | 5 #include "views/accessibility/native_view_accessibility_win.h" |
6 | 6 |
7 #include "ui/base/accessibility/accessible_view_state.h" | 7 #include "ui/base/accessibility/accessible_view_state.h" |
8 #include "ui/base/view_prop.h" | 8 #include "ui/base/view_prop.h" |
9 #include "views/controls/button/native_button.h" | 9 #include "views/controls/button/native_button.h" |
10 #include "views/widget/native_widget_win.h" | 10 #include "views/widget/native_widget_win.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 scoped_refptr<NativeViewAccessibilityWin> NativeViewAccessibilityWin::Create( | 21 scoped_refptr<NativeViewAccessibilityWin> NativeViewAccessibilityWin::Create( |
22 views::View* view) { | 22 views::View* view) { |
23 CComObject<NativeViewAccessibilityWin>* instance = NULL; | 23 CComObject<NativeViewAccessibilityWin>* instance = NULL; |
24 HRESULT hr = CComObject<NativeViewAccessibilityWin>::CreateInstance( | 24 HRESULT hr = CComObject<NativeViewAccessibilityWin>::CreateInstance( |
25 &instance); | 25 &instance); |
26 DCHECK(SUCCEEDED(hr)); | 26 DCHECK(SUCCEEDED(hr)); |
27 instance->set_view(view); | 27 instance->set_view(view); |
28 return scoped_refptr<NativeViewAccessibilityWin>(instance); | 28 return scoped_refptr<NativeViewAccessibilityWin>(instance); |
29 } | 29 } |
30 | 30 |
31 // static | |
32 IAccessible* NativeViewAccessibilityWin::GetAccessibleForView( | |
33 views::View* view) { | |
34 IAccessible* accessible = NULL; | |
35 | |
36 // First, check to see if the view is a native view. | |
37 if (view->GetClassName() == views::NativeViewHost::kViewClassName) { | |
38 views::NativeViewHost* native_host = | |
39 static_cast<views::NativeViewHost*>(view); | |
40 if (GetNativeIAccessibleInterface(native_host, &accessible) == S_OK) | |
41 return accessible; | |
42 } | |
43 | |
44 // Next, see if the view is a widget container. | |
45 if (view->GetChildWidget()) { | |
46 views::NativeWidgetWin* native_widget = | |
47 reinterpret_cast<views::NativeWidgetWin*>(view->GetChildWidget()); | |
48 if (GetNativeIAccessibleInterface( | |
49 native_widget->GetNativeView(), &accessible) == S_OK) { | |
50 return accessible; | |
51 } | |
52 } | |
53 | |
54 // Finally, use our NativeViewAccessibilityWin implementation. | |
55 return view->GetNativeViewAccessibilityWin(); | |
56 } | |
57 | |
58 NativeViewAccessibilityWin::NativeViewAccessibilityWin() : view_(NULL) { | 31 NativeViewAccessibilityWin::NativeViewAccessibilityWin() : view_(NULL) { |
59 } | 32 } |
60 | 33 |
61 NativeViewAccessibilityWin::~NativeViewAccessibilityWin() { | 34 NativeViewAccessibilityWin::~NativeViewAccessibilityWin() { |
62 } | 35 } |
63 | 36 |
64 // TODO(ctguil): Handle case where child View is not contained by parent. | 37 // TODO(ctguil): Handle case where child View is not contained by parent. |
65 STDMETHODIMP NativeViewAccessibilityWin::accHitTest( | 38 STDMETHODIMP NativeViewAccessibilityWin::accHitTest( |
66 LONG x_left, LONG y_top, VARIANT* child) { | 39 LONG x_left, LONG y_top, VARIANT* child) { |
67 if (!child) | 40 if (!child) |
(...skipping 11 matching lines...) Expand all Loading... |
79 return S_FALSE; | 52 return S_FALSE; |
80 } | 53 } |
81 | 54 |
82 views::View* view = view_->GetEventHandlerForPoint(point); | 55 views::View* view = view_->GetEventHandlerForPoint(point); |
83 if (view == view_) { | 56 if (view == view_) { |
84 // No child hit, return parent id. | 57 // No child hit, return parent id. |
85 child->vt = VT_I4; | 58 child->vt = VT_I4; |
86 child->lVal = CHILDID_SELF; | 59 child->lVal = CHILDID_SELF; |
87 } else { | 60 } else { |
88 child->vt = VT_DISPATCH; | 61 child->vt = VT_DISPATCH; |
89 child->pdispVal = GetAccessibleForView(view); | 62 child->pdispVal = view->GetNativeViewAccessible(); |
90 child->pdispVal->AddRef(); | 63 child->pdispVal->AddRef(); |
91 } | 64 } |
92 return S_OK; | 65 return S_OK; |
93 } | 66 } |
94 | 67 |
95 HRESULT NativeViewAccessibilityWin::accDoDefaultAction(VARIANT var_id) { | 68 HRESULT NativeViewAccessibilityWin::accDoDefaultAction(VARIANT var_id) { |
96 if (!IsValidId(var_id)) | 69 if (!IsValidId(var_id)) |
97 return E_INVALIDARG; | 70 return E_INVALIDARG; |
98 | 71 |
99 if (view_->GetClassName() == views::NativeButton::kViewClassName) { | 72 if (view_->GetClassName() == views::NativeButton::kViewClassName) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 return S_FALSE; | 122 return S_FALSE; |
150 } | 123 } |
151 | 124 |
152 // Set child_id based on first or last child. | 125 // Set child_id based on first or last child. |
153 int child_id = 0; | 126 int child_id = 0; |
154 if (nav_dir == NAVDIR_LASTCHILD) | 127 if (nav_dir == NAVDIR_LASTCHILD) |
155 child_id = view_->child_count() - 1; | 128 child_id = view_->child_count() - 1; |
156 | 129 |
157 views::View* child = view_->GetChildViewAt(child_id); | 130 views::View* child = view_->GetChildViewAt(child_id); |
158 end->vt = VT_DISPATCH; | 131 end->vt = VT_DISPATCH; |
159 end->pdispVal = GetAccessibleForView(child); | 132 end->pdispVal = child->GetNativeViewAccessible(); |
160 end->pdispVal->AddRef(); | 133 end->pdispVal->AddRef(); |
161 return S_OK; | 134 return S_OK; |
162 } | 135 } |
163 case NAVDIR_LEFT: | 136 case NAVDIR_LEFT: |
164 case NAVDIR_UP: | 137 case NAVDIR_UP: |
165 case NAVDIR_PREVIOUS: | 138 case NAVDIR_PREVIOUS: |
166 case NAVDIR_RIGHT: | 139 case NAVDIR_RIGHT: |
167 case NAVDIR_DOWN: | 140 case NAVDIR_DOWN: |
168 case NAVDIR_NEXT: { | 141 case NAVDIR_NEXT: { |
169 // Retrieve parent to access view index and perform bounds checking. | 142 // Retrieve parent to access view index and perform bounds checking. |
(...skipping 13 matching lines...) Expand all Loading... |
183 return S_FALSE; | 156 return S_FALSE; |
184 } else { | 157 } else { |
185 if (IsNavDirNext(nav_dir)) { | 158 if (IsNavDirNext(nav_dir)) { |
186 view_index += 1; | 159 view_index += 1; |
187 } else { | 160 } else { |
188 view_index -=1; | 161 view_index -=1; |
189 } | 162 } |
190 } | 163 } |
191 | 164 |
192 views::View* child = parent->GetChildViewAt(view_index); | 165 views::View* child = parent->GetChildViewAt(view_index); |
193 end->pdispVal = GetAccessibleForView(child); | 166 end->pdispVal = child->GetNativeViewAccessible(); |
194 end->vt = VT_DISPATCH; | 167 end->vt = VT_DISPATCH; |
195 end->pdispVal->AddRef(); | 168 end->pdispVal->AddRef(); |
196 return S_OK; | 169 return S_OK; |
197 } else { | 170 } else { |
198 // Check navigation bounds, adjusting for MSAA child indexing (MSAA | 171 // Check navigation bounds, adjusting for MSAA child indexing (MSAA |
199 // child indexing starts with 1, whereas View indexing starts with 0). | 172 // child indexing starts with 1, whereas View indexing starts with 0). |
200 if (!IsValidNav(nav_dir, start.lVal, 0, parent->child_count() + 1)) { | 173 if (!IsValidNav(nav_dir, start.lVal, 0, parent->child_count() + 1)) { |
201 // Navigation attempted to go out-of-bounds. | 174 // Navigation attempted to go out-of-bounds. |
202 end->vt = VT_EMPTY; | 175 end->vt = VT_EMPTY; |
203 return S_FALSE; | 176 return S_FALSE; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 view_->GetWidget()->native_widget()); | 236 view_->GetWidget()->native_widget()); |
264 child_view = widget->GetAccessibilityViewEventAt(child_id); | 237 child_view = widget->GetAccessibilityViewEventAt(child_id); |
265 } | 238 } |
266 | 239 |
267 if (!child_view) { | 240 if (!child_view) { |
268 // No child found. | 241 // No child found. |
269 *disp_child = NULL; | 242 *disp_child = NULL; |
270 return E_FAIL; | 243 return E_FAIL; |
271 } | 244 } |
272 | 245 |
273 *disp_child = GetAccessibleForView(child_view); | 246 *disp_child = child_view->GetNativeViewAccessible(); |
274 (*disp_child)->AddRef(); | 247 (*disp_child)->AddRef(); |
275 return S_OK; | 248 return S_OK; |
276 } | 249 } |
277 | 250 |
278 STDMETHODIMP NativeViewAccessibilityWin::get_accChildCount(LONG* child_count) { | 251 STDMETHODIMP NativeViewAccessibilityWin::get_accChildCount(LONG* child_count) { |
279 if (!child_count || !view_) | 252 if (!child_count || !view_) |
280 return E_INVALIDARG; | 253 return E_INVALIDARG; |
281 | 254 |
282 if (!view_) | 255 if (!view_) |
283 return E_FAIL; | 256 return E_FAIL; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 views::View* focus = NULL; | 310 views::View* focus = NULL; |
338 views::FocusManager* focus_manager = view_->GetFocusManager(); | 311 views::FocusManager* focus_manager = view_->GetFocusManager(); |
339 if (focus_manager) | 312 if (focus_manager) |
340 focus = focus_manager->GetFocusedView(); | 313 focus = focus_manager->GetFocusedView(); |
341 if (focus == view_) { | 314 if (focus == view_) { |
342 // This view has focus. | 315 // This view has focus. |
343 focus_child->vt = VT_I4; | 316 focus_child->vt = VT_I4; |
344 focus_child->lVal = CHILDID_SELF; | 317 focus_child->lVal = CHILDID_SELF; |
345 } else if (focus && view_->Contains(focus)) { | 318 } else if (focus && view_->Contains(focus)) { |
346 // Return the child object that has the keyboard focus. | 319 // Return the child object that has the keyboard focus. |
347 focus_child->pdispVal = GetAccessibleForView(focus); | 320 focus_child->pdispVal = focus->GetNativeViewAccessible(); |
348 focus_child->pdispVal->AddRef(); | 321 focus_child->pdispVal->AddRef(); |
349 return S_OK; | 322 return S_OK; |
350 } else { | 323 } else { |
351 // Neither this object nor any of its children has the keyboard focus. | 324 // Neither this object nor any of its children has the keyboard focus. |
352 focus_child->vt = VT_EMPTY; | 325 focus_child->vt = VT_EMPTY; |
353 } | 326 } |
354 return S_OK; | 327 return S_OK; |
355 } | 328 } |
356 | 329 |
357 STDMETHODIMP NativeViewAccessibilityWin::get_accKeyboardShortcut( | 330 STDMETHODIMP NativeViewAccessibilityWin::get_accKeyboardShortcut( |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
425 reinterpret_cast<void**>(disp_parent)); | 398 reinterpret_cast<void**>(disp_parent)); |
426 | 399 |
427 if (!SUCCEEDED(hr)) { | 400 if (!SUCCEEDED(hr)) { |
428 *disp_parent = NULL; | 401 *disp_parent = NULL; |
429 return S_FALSE; | 402 return S_FALSE; |
430 } | 403 } |
431 | 404 |
432 return S_OK; | 405 return S_OK; |
433 } | 406 } |
434 | 407 |
435 *disp_parent = GetAccessibleForView(parent_view); | 408 *disp_parent = parent_view->GetNativeViewAccessible(); |
436 (*disp_parent)->AddRef(); | 409 (*disp_parent)->AddRef(); |
437 return S_OK; | 410 return S_OK; |
438 } | 411 } |
439 | 412 |
440 STDMETHODIMP NativeViewAccessibilityWin::get_accRole( | 413 STDMETHODIMP NativeViewAccessibilityWin::get_accRole( |
441 VARIANT var_id, VARIANT* role) { | 414 VARIANT var_id, VARIANT* role) { |
442 if (!IsValidId(var_id) || !role) | 415 if (!IsValidId(var_id) || !role) |
443 return E_INVALIDARG; | 416 return E_INVALIDARG; |
444 | 417 |
445 if (!view_) | 418 if (!view_) |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 if (state & AccessibilityTypes::STATE_READONLY) | 690 if (state & AccessibilityTypes::STATE_READONLY) |
718 msaa_state |= STATE_SYSTEM_READONLY; | 691 msaa_state |= STATE_SYSTEM_READONLY; |
719 if (state & AccessibilityTypes::STATE_SELECTED) | 692 if (state & AccessibilityTypes::STATE_SELECTED) |
720 msaa_state |= STATE_SYSTEM_SELECTED; | 693 msaa_state |= STATE_SYSTEM_SELECTED; |
721 if (state & AccessibilityTypes::STATE_FOCUSED) | 694 if (state & AccessibilityTypes::STATE_FOCUSED) |
722 msaa_state |= STATE_SYSTEM_FOCUSED; | 695 msaa_state |= STATE_SYSTEM_FOCUSED; |
723 if (state & AccessibilityTypes::STATE_UNAVAILABLE) | 696 if (state & AccessibilityTypes::STATE_UNAVAILABLE) |
724 msaa_state |= STATE_SYSTEM_UNAVAILABLE; | 697 msaa_state |= STATE_SYSTEM_UNAVAILABLE; |
725 return msaa_state; | 698 return msaa_state; |
726 } | 699 } |
727 | |
728 // static | |
729 HRESULT NativeViewAccessibilityWin::GetNativeIAccessibleInterface( | |
730 views::NativeViewHost* native_host, IAccessible** accessible) { | |
731 if (!native_host || !accessible) | |
732 return E_INVALIDARG; | |
733 | |
734 HWND native_view_window = static_cast<HWND>( | |
735 ui::ViewProp::GetValue(native_host->native_view(), | |
736 views::kViewsNativeHostPropForAccessibility)); | |
737 if (!IsWindow(native_view_window)) { | |
738 native_view_window = native_host->native_view(); | |
739 } | |
740 | |
741 return GetNativeIAccessibleInterface(native_view_window, accessible); | |
742 } | |
743 | |
744 // static | |
745 HRESULT NativeViewAccessibilityWin::GetNativeIAccessibleInterface( | |
746 HWND native_view_window , IAccessible** accessible) { | |
747 if (IsWindow(native_view_window)) { | |
748 LRESULT ret = SendMessage(native_view_window, WM_GETOBJECT, 0, | |
749 OBJID_CLIENT); | |
750 return ObjectFromLresult(ret, IID_IDispatch, 0, | |
751 reinterpret_cast<void**>(accessible)); | |
752 } | |
753 | |
754 return E_FAIL; | |
755 } | |
OLD | NEW |