| OLD | NEW | 
|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/view_accessibility.h" | 5 #include "views/accessibility/view_accessibility.h" | 
| 6 | 6 | 
| 7 #include "ui/base/view_prop.h" | 7 #include "ui/base/view_prop.h" | 
| 8 #include "views/controls/button/native_button.h" | 8 #include "views/controls/button/native_button.h" | 
| 9 #include "views/widget/widget.h" | 9 #include "views/widget/widget.h" | 
| 10 #include "views/widget/widget_win.h" | 10 #include "views/widget/widget_win.h" | 
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 101 } | 101 } | 
| 102 | 102 | 
| 103 STDMETHODIMP ViewAccessibility::accLocation( | 103 STDMETHODIMP ViewAccessibility::accLocation( | 
| 104     LONG* x_left, LONG* y_top, LONG* width, LONG* height, VARIANT var_id) { | 104     LONG* x_left, LONG* y_top, LONG* width, LONG* height, VARIANT var_id) { | 
| 105   if (!IsValidId(var_id) || !x_left || !y_top || !width || !height) | 105   if (!IsValidId(var_id) || !x_left || !y_top || !width || !height) | 
| 106     return E_INVALIDARG; | 106     return E_INVALIDARG; | 
| 107 | 107 | 
| 108   if (!view_) | 108   if (!view_) | 
| 109     return E_FAIL; | 109     return E_FAIL; | 
| 110 | 110 | 
| 111   gfx::Rect view_bounds; | 111   if (!view_->bounds().IsEmpty()) { | 
| 112   // Retrieving the parent View to be used for converting from view-to-screen | 112     *width  = view_->width(); | 
| 113   // coordinates. | 113     *height = view_->height(); | 
| 114   views::View* parent = view_->GetParent(); | 114     gfx::Point topleft(view_->bounds().origin()); | 
| 115 | 115     views::View::ConvertPointToScreen(view_->parent() ? view_->parent() : view_, | 
| 116   if (parent == NULL) { | 116                                       &topleft); | 
| 117     // If no parent, remain within the same View. |  | 
| 118     parent = view_; |  | 
| 119   } |  | 
| 120 |  | 
| 121   // Retrieve active View's bounds. |  | 
| 122   view_bounds = view_->bounds(); |  | 
| 123 |  | 
| 124   if (!view_bounds.IsEmpty()) { |  | 
| 125     *width  = view_bounds.width(); |  | 
| 126     *height = view_bounds.height(); |  | 
| 127 |  | 
| 128     gfx::Point topleft(view_bounds.origin()); |  | 
| 129     views::View::ConvertPointToScreen(parent, &topleft); |  | 
| 130     *x_left = topleft.x(); | 117     *x_left = topleft.x(); | 
| 131     *y_top  = topleft.y(); | 118     *y_top  = topleft.y(); | 
| 132   } else { | 119   } else { | 
| 133     return E_FAIL; | 120     return E_FAIL; | 
| 134   } | 121   } | 
| 135   return S_OK; | 122   return S_OK; | 
| 136 } | 123 } | 
| 137 | 124 | 
| 138 STDMETHODIMP ViewAccessibility::accNavigate(LONG nav_dir, VARIANT start, | 125 STDMETHODIMP ViewAccessibility::accNavigate(LONG nav_dir, VARIANT start, | 
| 139                                             VARIANT* end) { | 126                                             VARIANT* end) { | 
| 140   if (start.vt != VT_I4 || !end) | 127   if (start.vt != VT_I4 || !end) | 
| 141     return E_INVALIDARG; | 128     return E_INVALIDARG; | 
| 142 | 129 | 
| 143   if (!view_) | 130   if (!view_) | 
| 144     return E_FAIL; | 131     return E_FAIL; | 
| 145 | 132 | 
| 146   switch (nav_dir) { | 133   switch (nav_dir) { | 
| 147     case NAVDIR_FIRSTCHILD: | 134     case NAVDIR_FIRSTCHILD: | 
| 148     case NAVDIR_LASTCHILD: { | 135     case NAVDIR_LASTCHILD: { | 
| 149       if (start.lVal != CHILDID_SELF) { | 136       if (start.lVal != CHILDID_SELF) { | 
| 150         // Start of navigation must be on the View itself. | 137         // Start of navigation must be on the View itself. | 
| 151         return E_INVALIDARG; | 138         return E_INVALIDARG; | 
| 152       } else if (view_->GetChildViewCount() == 0) { | 139       } else if (!view_->has_children()) { | 
| 153         // No children found. | 140         // No children found. | 
| 154         return S_FALSE; | 141         return S_FALSE; | 
| 155       } | 142       } | 
| 156 | 143 | 
| 157       // Set child_id based on first or last child. | 144       // Set child_id based on first or last child. | 
| 158       int child_id = 0; | 145       int child_id = 0; | 
| 159       if (nav_dir == NAVDIR_LASTCHILD) { | 146       if (nav_dir == NAVDIR_LASTCHILD) | 
| 160         child_id = view_->GetChildViewCount() - 1; | 147         child_id = view_->child_count() - 1; | 
| 161       } |  | 
| 162 | 148 | 
| 163       views::View* child = view_->GetChildViewAt(child_id); | 149       views::View* child = view_->GetChildViewAt(child_id); | 
| 164       end->vt = VT_DISPATCH; | 150       end->vt = VT_DISPATCH; | 
| 165       end->pdispVal = GetAccessibleForView(child); | 151       end->pdispVal = GetAccessibleForView(child); | 
| 166       end->pdispVal->AddRef(); | 152       end->pdispVal->AddRef(); | 
| 167       return S_OK; | 153       return S_OK; | 
| 168     } | 154     } | 
| 169     case NAVDIR_LEFT: | 155     case NAVDIR_LEFT: | 
| 170     case NAVDIR_UP: | 156     case NAVDIR_UP: | 
| 171     case NAVDIR_PREVIOUS: | 157     case NAVDIR_PREVIOUS: | 
| 172     case NAVDIR_RIGHT: | 158     case NAVDIR_RIGHT: | 
| 173     case NAVDIR_DOWN: | 159     case NAVDIR_DOWN: | 
| 174     case NAVDIR_NEXT: { | 160     case NAVDIR_NEXT: { | 
| 175       // Retrieve parent to access view index and perform bounds checking. | 161       // Retrieve parent to access view index and perform bounds checking. | 
| 176       views::View* parent = view_->GetParent(); | 162       views::View* parent = view_->parent(); | 
| 177       if (!parent) { | 163       if (!parent) { | 
| 178         return E_FAIL; | 164         return E_FAIL; | 
| 179       } | 165       } | 
| 180 | 166 | 
| 181       if (start.lVal == CHILDID_SELF) { | 167       if (start.lVal == CHILDID_SELF) { | 
| 182         int view_index = parent->GetChildIndex(view_); | 168         int view_index = parent->GetIndexOf(view_); | 
| 183         // Check navigation bounds, adjusting for View child indexing (MSAA | 169         // Check navigation bounds, adjusting for View child indexing (MSAA | 
| 184         // child indexing starts with 1, whereas View indexing starts with 0). | 170         // child indexing starts with 1, whereas View indexing starts with 0). | 
| 185         if (!IsValidNav(nav_dir, view_index, -1, | 171         if (!IsValidNav(nav_dir, view_index, -1, | 
| 186                         parent->GetChildViewCount() - 1)) { | 172                         parent->child_count() - 1)) { | 
| 187           // Navigation attempted to go out-of-bounds. | 173           // Navigation attempted to go out-of-bounds. | 
| 188           end->vt = VT_EMPTY; | 174           end->vt = VT_EMPTY; | 
| 189           return S_FALSE; | 175           return S_FALSE; | 
| 190         } else { | 176         } else { | 
| 191           if (IsNavDirNext(nav_dir)) { | 177           if (IsNavDirNext(nav_dir)) { | 
| 192             view_index += 1; | 178             view_index += 1; | 
| 193           } else { | 179           } else { | 
| 194             view_index -=1; | 180             view_index -=1; | 
| 195           } | 181           } | 
| 196         } | 182         } | 
| 197 | 183 | 
| 198         views::View* child = parent->GetChildViewAt(view_index); | 184         views::View* child = parent->GetChildViewAt(view_index); | 
| 199         end->pdispVal = GetAccessibleForView(child); | 185         end->pdispVal = GetAccessibleForView(child); | 
| 200         end->vt = VT_DISPATCH; | 186         end->vt = VT_DISPATCH; | 
| 201         end->pdispVal->AddRef(); | 187         end->pdispVal->AddRef(); | 
| 202         return S_OK; | 188         return S_OK; | 
| 203       } else { | 189       } else { | 
| 204         // Check navigation bounds, adjusting for MSAA child indexing (MSAA | 190         // Check navigation bounds, adjusting for MSAA child indexing (MSAA | 
| 205         // child indexing starts with 1, whereas View indexing starts with 0). | 191         // child indexing starts with 1, whereas View indexing starts with 0). | 
| 206         if (!IsValidNav(nav_dir, start.lVal, 0, | 192         if (!IsValidNav(nav_dir, start.lVal, 0, parent->child_count() + 1)) { | 
| 207                         parent->GetChildViewCount() + 1)) { |  | 
| 208             // Navigation attempted to go out-of-bounds. | 193             // Navigation attempted to go out-of-bounds. | 
| 209             end->vt = VT_EMPTY; | 194             end->vt = VT_EMPTY; | 
| 210             return S_FALSE; | 195             return S_FALSE; | 
| 211           } else { | 196           } else { | 
| 212             if (IsNavDirNext(nav_dir)) { | 197             if (IsNavDirNext(nav_dir)) { | 
| 213               start.lVal += 1; | 198               start.lVal += 1; | 
| 214             } else { | 199             } else { | 
| 215               start.lVal -= 1; | 200               start.lVal -= 1; | 
| 216             } | 201             } | 
| 217         } | 202         } | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
| 248 | 233 | 
| 249   LONG child_id = V_I4(&var_child); | 234   LONG child_id = V_I4(&var_child); | 
| 250 | 235 | 
| 251   if (child_id == CHILDID_SELF) { | 236   if (child_id == CHILDID_SELF) { | 
| 252     // Remain with the same dispatch. | 237     // Remain with the same dispatch. | 
| 253     return S_OK; | 238     return S_OK; | 
| 254   } | 239   } | 
| 255 | 240 | 
| 256   views::View* child_view = NULL; | 241   views::View* child_view = NULL; | 
| 257   if (child_id > 0) { | 242   if (child_id > 0) { | 
| 258     if (child_id <= view_->GetChildViewCount()) { | 243     int child_id_as_index = child_id - 1; | 
|  | 244     if (child_id_as_index < view_->child_count()) { | 
| 259       // Note: child_id is a one based index when indexing children. | 245       // Note: child_id is a one based index when indexing children. | 
| 260       child_view = view_->GetChildViewAt(child_id - 1); | 246       child_view = view_->GetChildViewAt(child_id_as_index); | 
| 261     } else { | 247     } else { | 
| 262       // Attempt to retrieve a child view with the specified id. | 248       // Attempt to retrieve a child view with the specified id. | 
| 263       child_view = view_->GetViewByID(child_id); | 249       child_view = view_->GetViewByID(child_id); | 
| 264     } | 250     } | 
| 265   } else { | 251   } else { | 
| 266     // Negative values are used for events fired using the view's WidgetWin | 252     // Negative values are used for events fired using the view's WidgetWin | 
| 267     views::WidgetWin* widget = | 253     views::WidgetWin* widget = | 
| 268         static_cast<views::WidgetWin*>(view_->GetWidget()); | 254         static_cast<views::WidgetWin*>(view_->GetWidget()); | 
| 269     child_view = widget->GetAccessibilityViewEventAt(child_id); | 255     child_view = widget->GetAccessibilityViewEventAt(child_id); | 
| 270   } | 256   } | 
| 271 | 257 | 
| 272   if (!child_view) { | 258   if (!child_view) { | 
| 273     // No child found. | 259     // No child found. | 
| 274     *disp_child = NULL; | 260     *disp_child = NULL; | 
| 275     return E_FAIL; | 261     return E_FAIL; | 
| 276   } | 262   } | 
| 277 | 263 | 
| 278   *disp_child = GetAccessibleForView(child_view); | 264   *disp_child = GetAccessibleForView(child_view); | 
| 279   (*disp_child)->AddRef(); | 265   (*disp_child)->AddRef(); | 
| 280   return S_OK; | 266   return S_OK; | 
| 281 } | 267 } | 
| 282 | 268 | 
| 283 STDMETHODIMP ViewAccessibility::get_accChildCount(LONG* child_count) { | 269 STDMETHODIMP ViewAccessibility::get_accChildCount(LONG* child_count) { | 
| 284   if (!child_count || !view_) | 270   if (!child_count || !view_) | 
| 285     return E_INVALIDARG; | 271     return E_INVALIDARG; | 
| 286 | 272 | 
| 287   if (!view_) | 273   if (!view_) | 
| 288     return E_FAIL; | 274     return E_FAIL; | 
| 289 | 275 | 
| 290   *child_count = view_->GetChildViewCount(); | 276   *child_count = view_->child_count(); | 
| 291   return S_OK; | 277   return S_OK; | 
| 292 } | 278 } | 
| 293 | 279 | 
| 294 STDMETHODIMP ViewAccessibility::get_accDefaultAction( | 280 STDMETHODIMP ViewAccessibility::get_accDefaultAction( | 
| 295     VARIANT var_id, BSTR* def_action) { | 281     VARIANT var_id, BSTR* def_action) { | 
| 296   if (!IsValidId(var_id) || !def_action) | 282   if (!IsValidId(var_id) || !def_action) | 
| 297     return E_INVALIDARG; | 283     return E_INVALIDARG; | 
| 298 | 284 | 
| 299   if (!view_) | 285   if (!view_) | 
| 300     return E_FAIL; | 286     return E_FAIL; | 
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 337     return E_FAIL; | 323     return E_FAIL; | 
| 338 | 324 | 
| 339   views::View* focus = NULL; | 325   views::View* focus = NULL; | 
| 340   views::FocusManager* focus_manager = view_->GetFocusManager(); | 326   views::FocusManager* focus_manager = view_->GetFocusManager(); | 
| 341   if (focus_manager) | 327   if (focus_manager) | 
| 342     focus = focus_manager->GetFocusedView(); | 328     focus = focus_manager->GetFocusedView(); | 
| 343   if (focus == view_) { | 329   if (focus == view_) { | 
| 344     // This view has focus. | 330     // This view has focus. | 
| 345     focus_child->vt = VT_I4; | 331     focus_child->vt = VT_I4; | 
| 346     focus_child->lVal = CHILDID_SELF; | 332     focus_child->lVal = CHILDID_SELF; | 
| 347   } else if (focus && view_->IsParentOf(focus)) { | 333   } else if (focus && view_->Contains(focus)) { | 
| 348     // Return the child object that has the keyboard focus. | 334     // Return the child object that has the keyboard focus. | 
| 349     focus_child->pdispVal = GetAccessibleForView(focus); | 335     focus_child->pdispVal = GetAccessibleForView(focus); | 
| 350     focus_child->pdispVal->AddRef(); | 336     focus_child->pdispVal->AddRef(); | 
| 351     return S_OK; | 337     return S_OK; | 
| 352   } else { | 338   } else { | 
| 353     // Neither this object nor any of its children has the keyboard focus. | 339     // Neither this object nor any of its children has the keyboard focus. | 
| 354     focus_child->vt = VT_EMPTY; | 340     focus_child->vt = VT_EMPTY; | 
| 355   } | 341   } | 
| 356   return S_OK; | 342   return S_OK; | 
| 357 } | 343 } | 
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 397   return S_OK; | 383   return S_OK; | 
| 398 } | 384 } | 
| 399 | 385 | 
| 400 STDMETHODIMP ViewAccessibility::get_accParent(IDispatch** disp_parent) { | 386 STDMETHODIMP ViewAccessibility::get_accParent(IDispatch** disp_parent) { | 
| 401   if (!disp_parent) | 387   if (!disp_parent) | 
| 402     return E_INVALIDARG; | 388     return E_INVALIDARG; | 
| 403 | 389 | 
| 404   if (!view_) | 390   if (!view_) | 
| 405     return E_FAIL; | 391     return E_FAIL; | 
| 406 | 392 | 
| 407   views::View* parent_view = view_->GetParent(); | 393   views::View* parent_view = view_->parent(); | 
| 408 | 394 | 
| 409   if (!parent_view) { | 395   if (!parent_view) { | 
| 410     // This function can get called during teardown of WidetWin so we | 396     // This function can get called during teardown of WidetWin so we | 
| 411     // should bail out if we fail to get the HWND. | 397     // should bail out if we fail to get the HWND. | 
| 412     if (!view_->GetWidget() || !view_->GetWidget()->GetNativeView()) { | 398     if (!view_->GetWidget() || !view_->GetWidget()->GetNativeView()) { | 
| 413       *disp_parent = NULL; | 399       *disp_parent = NULL; | 
| 414       return S_FALSE; | 400       return S_FALSE; | 
| 415     } | 401     } | 
| 416 | 402 | 
| 417     // For a View that has no parent (e.g. root), point the accessible parent to | 403     // For a View that has no parent (e.g. root), point the accessible parent to | 
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 521 void ViewAccessibility::SetState(VARIANT* msaa_state, views::View* view) { | 507 void ViewAccessibility::SetState(VARIANT* msaa_state, views::View* view) { | 
| 522   // Ensure the output param is initialized to zero. | 508   // Ensure the output param is initialized to zero. | 
| 523   msaa_state->lVal = 0; | 509   msaa_state->lVal = 0; | 
| 524 | 510 | 
| 525   // Default state; all views can have accessibility focus. | 511   // Default state; all views can have accessibility focus. | 
| 526   msaa_state->lVal |= STATE_SYSTEM_FOCUSABLE; | 512   msaa_state->lVal |= STATE_SYSTEM_FOCUSABLE; | 
| 527 | 513 | 
| 528   if (!view) | 514   if (!view) | 
| 529     return; | 515     return; | 
| 530 | 516 | 
| 531   if (!view->IsEnabled()) { | 517   if (!view->IsEnabled()) | 
| 532     msaa_state->lVal |= STATE_SYSTEM_UNAVAILABLE; | 518     msaa_state->lVal |= STATE_SYSTEM_UNAVAILABLE; | 
| 533   } | 519   if (!view->IsVisible()) | 
| 534   if (!view->IsVisible()) { |  | 
| 535     msaa_state->lVal |= STATE_SYSTEM_INVISIBLE; | 520     msaa_state->lVal |= STATE_SYSTEM_INVISIBLE; | 
| 536   } | 521   if (view->IsHotTracked()) | 
| 537   if (view->IsHotTracked()) { |  | 
| 538     msaa_state->lVal |= STATE_SYSTEM_HOTTRACKED; | 522     msaa_state->lVal |= STATE_SYSTEM_HOTTRACKED; | 
| 539   } | 523   if (view->IsPushed()) | 
| 540   if (view->IsPushed()) { |  | 
| 541     msaa_state->lVal |= STATE_SYSTEM_PRESSED; | 524     msaa_state->lVal |= STATE_SYSTEM_PRESSED; | 
| 542   } |  | 
| 543   // Check both for actual View focus, as well as accessibility focus. |  | 
| 544   views::View* parent = view->GetParent(); |  | 
| 545 |  | 
| 546   if (view->HasFocus()) | 525   if (view->HasFocus()) | 
| 547     msaa_state->lVal |= STATE_SYSTEM_FOCUSED; | 526     msaa_state->lVal |= STATE_SYSTEM_FOCUSED; | 
| 548 | 527 | 
| 549   // Add on any view-specific states. | 528   // Add on any view-specific states. | 
| 550   msaa_state->lVal |= MSAAState(view->GetAccessibleState()); | 529   msaa_state->lVal |= MSAAState(view->GetAccessibleState()); | 
| 551 } | 530 } | 
| 552 | 531 | 
| 553 // IAccessible functions not supported. | 532 // IAccessible functions not supported. | 
| 554 | 533 | 
| 555 STDMETHODIMP ViewAccessibility::get_accSelection(VARIANT* selected) { | 534 STDMETHODIMP ViewAccessibility::get_accSelection(VARIANT* selected) { | 
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 739     HWND native_view_window , IAccessible** accessible) { | 718     HWND native_view_window , IAccessible** accessible) { | 
| 740   if (IsWindow(native_view_window)) { | 719   if (IsWindow(native_view_window)) { | 
| 741     LRESULT ret = SendMessage(native_view_window, WM_GETOBJECT, 0, | 720     LRESULT ret = SendMessage(native_view_window, WM_GETOBJECT, 0, | 
| 742                               OBJID_CLIENT); | 721                               OBJID_CLIENT); | 
| 743     return ObjectFromLresult(ret, IID_IDispatch, 0, | 722     return ObjectFromLresult(ret, IID_IDispatch, 0, | 
| 744                              reinterpret_cast<void**>(accessible)); | 723                              reinterpret_cast<void**>(accessible)); | 
| 745   } | 724   } | 
| 746 | 725 | 
| 747   return E_FAIL; | 726   return E_FAIL; | 
| 748 } | 727 } | 
| OLD | NEW | 
|---|