| 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 |