Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ui/views/accessibility/native_view_accessibility_win.h" | 5 #include "ui/views/accessibility/native_view_accessibility_win.h" |
| 6 | 6 |
| 7 #include <oleacc.h> | 7 #include <oleacc.h> |
| 8 #include <UIAutomationClient.h> | 8 #include <UIAutomationClient.h> |
| 9 | 9 |
| 10 #include <set> | 10 #include <set> |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 182 IID_IAccessible, IID_IAccessible2, | 182 IID_IAccessible, IID_IAccessible2, |
| 183 reinterpret_cast<void**>(iaccessible2.Receive())); | 183 reinterpret_cast<void**>(iaccessible2.Receive())); |
| 184 } | 184 } |
| 185 | 185 |
| 186 } // anonymous namespace | 186 } // anonymous namespace |
| 187 | 187 |
| 188 // static | 188 // static |
| 189 long NativeViewAccessibilityWin::next_unique_id_ = 1; | 189 long NativeViewAccessibilityWin::next_unique_id_ = 1; |
| 190 int NativeViewAccessibilityWin::view_storage_ids_[kMaxViewStorageIds] = {0}; | 190 int NativeViewAccessibilityWin::view_storage_ids_[kMaxViewStorageIds] = {0}; |
| 191 int NativeViewAccessibilityWin::next_view_storage_id_index_ = 0; | 191 int NativeViewAccessibilityWin::next_view_storage_id_index_ = 0; |
| 192 std::vector<int> NativeViewAccessibilityWin::alert_target_view_storage_ids_; | |
| 192 | 193 |
| 193 // static | 194 // static |
| 194 NativeViewAccessibility* NativeViewAccessibility::Create(View* view) { | 195 NativeViewAccessibility* NativeViewAccessibility::Create(View* view) { |
| 195 // Make sure ATL is initialized in this module. | 196 // Make sure ATL is initialized in this module. |
| 196 ui::win::CreateATLModuleIfNeeded(); | 197 ui::win::CreateATLModuleIfNeeded(); |
| 197 | 198 |
| 198 CComObject<NativeViewAccessibilityWin>* instance = NULL; | 199 CComObject<NativeViewAccessibilityWin>* instance = NULL; |
| 199 HRESULT hr = CComObject<NativeViewAccessibilityWin>::CreateInstance( | 200 HRESULT hr = CComObject<NativeViewAccessibilityWin>::CreateInstance( |
| 200 &instance); | 201 &instance); |
| 201 DCHECK(SUCCEEDED(hr)); | 202 DCHECK(SUCCEEDED(hr)); |
| 202 instance->set_view(view); | 203 instance->set_view(view); |
| 203 instance->AddRef(); | 204 instance->AddRef(); |
| 204 return instance; | 205 return instance; |
| 205 } | 206 } |
| 206 | 207 |
| 207 NativeViewAccessibilityWin::NativeViewAccessibilityWin() | 208 NativeViewAccessibilityWin::NativeViewAccessibilityWin() |
| 208 : view_(NULL), | 209 : view_(NULL), |
| 209 unique_id_(next_unique_id_++) { | 210 unique_id_(next_unique_id_++) { |
| 210 } | 211 } |
| 211 | 212 |
| 212 NativeViewAccessibilityWin::~NativeViewAccessibilityWin() { | 213 NativeViewAccessibilityWin::~NativeViewAccessibilityWin() { |
| 214 RemoveAlertTarget(); | |
| 213 } | 215 } |
| 214 | 216 |
| 215 void NativeViewAccessibilityWin::NotifyAccessibilityEvent( | 217 void NativeViewAccessibilityWin::NotifyAccessibilityEvent( |
| 216 ui::AXEvent event_type) { | 218 ui::AXEvent event_type) { |
| 217 if (!view_) | 219 if (!view_) |
| 218 return; | 220 return; |
| 219 | 221 |
| 220 ViewStorage* view_storage = ViewStorage::GetInstance(); | 222 ViewStorage* view_storage = ViewStorage::GetInstance(); |
| 221 HWND hwnd = HWNDForView(view_); | 223 HWND hwnd = HWNDForView(view_); |
| 222 int view_storage_id = view_storage_ids_[next_view_storage_id_index_]; | 224 int view_storage_id = view_storage_ids_[next_view_storage_id_index_]; |
| 223 if (view_storage_id == 0) { | 225 if (view_storage_id == 0) { |
| 224 view_storage_id = view_storage->CreateStorageID(); | 226 view_storage_id = view_storage->CreateStorageID(); |
| 225 view_storage_ids_[next_view_storage_id_index_] = view_storage_id; | 227 view_storage_ids_[next_view_storage_id_index_] = view_storage_id; |
| 226 } else { | 228 } else { |
| 227 view_storage->RemoveView(view_storage_id); | 229 view_storage->RemoveView(view_storage_id); |
| 228 } | 230 } |
| 229 view_storage->StoreView(view_storage_id, view_); | 231 view_storage->StoreView(view_storage_id, view_); |
| 230 | 232 |
| 231 // Positive child ids are used for enumerating direct children, | 233 // Positive child ids are used for enumerating direct children, |
| 232 // negative child ids can be used as unique ids to refer to a specific | 234 // negative child ids can be used as unique ids to refer to a specific |
| 233 // descendants. Make index into view_storage_ids_ into a negative child id. | 235 // descendants. Make index into view_storage_ids_ into a negative child id. |
| 234 int child_id = | 236 int child_id = |
| 235 base::win::kFirstViewsAccessibilityId - next_view_storage_id_index_; | 237 base::win::kFirstViewsAccessibilityId - next_view_storage_id_index_; |
| 236 ::NotifyWinEvent(MSAAEvent(event_type), hwnd, OBJID_CLIENT, child_id); | 238 ::NotifyWinEvent(MSAAEvent(event_type), hwnd, OBJID_CLIENT, child_id); |
| 237 next_view_storage_id_index_ = | 239 next_view_storage_id_index_ = |
| 238 (next_view_storage_id_index_ + 1) % kMaxViewStorageIds; | 240 (next_view_storage_id_index_ + 1) % kMaxViewStorageIds; |
| 241 | |
| 242 // Keep track of views that are a target of an alert event. | |
| 243 if (event_type == ui::AX_EVENT_ALERT) | |
| 244 AddAlertTarget(); | |
| 239 } | 245 } |
| 240 | 246 |
| 241 gfx::NativeViewAccessible NativeViewAccessibilityWin::GetNativeObject() { | 247 gfx::NativeViewAccessible NativeViewAccessibilityWin::GetNativeObject() { |
| 242 return this; | 248 return this; |
| 243 } | 249 } |
| 244 | 250 |
| 245 void NativeViewAccessibilityWin::Destroy() { | 251 void NativeViewAccessibilityWin::Destroy() { |
| 246 view_ = NULL; | 252 view_ = NULL; |
| 247 Release(); | 253 Release(); |
| 248 } | 254 } |
| (...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 858 if (!view_) | 864 if (!view_) |
| 859 return E_FAIL; | 865 return E_FAIL; |
| 860 | 866 |
| 861 if (!window_handle) | 867 if (!window_handle) |
| 862 return E_INVALIDARG; | 868 return E_INVALIDARG; |
| 863 | 869 |
| 864 *window_handle = HWNDForView(view_); | 870 *window_handle = HWNDForView(view_); |
| 865 return *window_handle ? S_OK : S_FALSE; | 871 return *window_handle ? S_OK : S_FALSE; |
| 866 } | 872 } |
| 867 | 873 |
| 874 STDMETHODIMP NativeViewAccessibilityWin::get_relationTargetsOfType( | |
| 875 BSTR type_bstr, | |
| 876 long max_targets, | |
| 877 IUnknown ***targets, | |
| 878 long *n_targets) { | |
| 879 if (!view_) | |
| 880 return E_FAIL; | |
| 881 | |
| 882 // Only respond to requests for relations of type "alerts" on the | |
| 883 // root view. | |
| 884 base::string16 type(type_bstr); | |
| 885 if (type != L"alerts" || view_->parent()) | |
| 886 return S_FALSE; | |
|
David Tseng
2014/05/08 17:23:55
Is this string defined in any header?
dmazzoni
2014/05/08 19:16:13
This is a new convention with NV Access, we want t
| |
| 887 | |
| 888 // Collect all of the alert views that are still valid. | |
| 889 std::vector<View*> alert_views; | |
| 890 ViewStorage* view_storage = ViewStorage::GetInstance(); | |
| 891 for (size_t i = 0; i < alert_target_view_storage_ids_.size(); ++i) { | |
| 892 int view_storage_id = alert_target_view_storage_ids_[i]; | |
| 893 View* view = view_storage->RetrieveView(view_storage_id); | |
| 894 if (!view || !view_->Contains(view)) | |
| 895 continue; | |
| 896 alert_views.push_back(view); | |
| 897 } | |
| 898 | |
| 899 long count = alert_views.size(); | |
| 900 if (count == 0) { | |
| 901 if (n_targets) | |
|
David Tseng
2014/05/08 17:23:55
If this isn't true, we should return E_INVALIDARG
dmazzoni
2014/05/08 19:16:13
Done.
| |
| 902 *n_targets = 0; | |
| 903 if (targets) | |
| 904 *targets = NULL; | |
| 905 return S_FALSE; | |
| 906 } | |
| 907 | |
| 908 // The caller is allowed to specify max_targets=0 to return all of them. | |
| 909 if (max_targets > 0 && count > max_targets) | |
|
David Tseng
2014/05/08 17:23:55
The below if clause doesn't do what this comment s
dmazzoni
2014/05/08 19:16:13
I think this is right, please take another look. I
| |
| 910 count = max_targets; | |
| 911 | |
|
David Tseng
2014/05/08 17:23:55
What happens if max_targets > count?
dmazzoni
2014/05/08 19:16:13
It should return |count| targets.
| |
| 912 // Return the number of targets. | |
| 913 if (n_targets) | |
| 914 *n_targets = count; | |
| 915 | |
| 916 // Allocate COM memory for the result array and populate it. | |
| 917 if (targets) { | |
| 918 *targets = static_cast<IUnknown**>( | |
| 919 CoTaskMemAlloc(count * sizeof(IUnknown*))); | |
| 920 for (long i = 0; i < count; ++i) { | |
| 921 (*targets)[i] = alert_views[i]->GetNativeViewAccessible(); | |
| 922 (*targets)[i]->AddRef(); | |
| 923 } | |
| 924 } | |
| 925 return S_OK; | |
| 926 } | |
| 927 | |
| 868 // | 928 // |
| 869 // IAccessibleText | 929 // IAccessibleText |
| 870 // | 930 // |
| 871 | 931 |
| 872 STDMETHODIMP NativeViewAccessibilityWin::get_nCharacters(LONG* n_characters) { | 932 STDMETHODIMP NativeViewAccessibilityWin::get_nCharacters(LONG* n_characters) { |
| 873 if (!view_) | 933 if (!view_) |
| 874 return E_FAIL; | 934 return E_FAIL; |
| 875 | 935 |
| 876 if (!n_characters) | 936 if (!n_characters) |
| 877 return E_INVALIDARG; | 937 return E_INVALIDARG; |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1064 | 1124 |
| 1065 // | 1125 // |
| 1066 // IServiceProvider methods. | 1126 // IServiceProvider methods. |
| 1067 // | 1127 // |
| 1068 | 1128 |
| 1069 STDMETHODIMP NativeViewAccessibilityWin::QueryService( | 1129 STDMETHODIMP NativeViewAccessibilityWin::QueryService( |
| 1070 REFGUID guidService, REFIID riid, void** object) { | 1130 REFGUID guidService, REFIID riid, void** object) { |
| 1071 if (!view_) | 1131 if (!view_) |
| 1072 return E_FAIL; | 1132 return E_FAIL; |
| 1073 | 1133 |
| 1074 if (riid == IID_IAccessible2) | 1134 if (riid == IID_IAccessible2 || riid == IID_IAccessible2_2) |
| 1075 AccessibleWebViewRegistry::GetInstance()->EnableIAccessible2Support(); | 1135 AccessibleWebViewRegistry::GetInstance()->EnableIAccessible2Support(); |
| 1076 | 1136 |
| 1077 if (guidService == IID_IAccessible || | 1137 if (guidService == IID_IAccessible || |
| 1078 guidService == IID_IAccessible2 || | 1138 guidService == IID_IAccessible2 || |
| 1139 guidService == IID_IAccessible2_2 || | |
| 1079 guidService == IID_IAccessibleText) { | 1140 guidService == IID_IAccessibleText) { |
| 1080 return QueryInterface(riid, object); | 1141 return QueryInterface(riid, object); |
| 1081 } | 1142 } |
| 1082 | 1143 |
| 1083 // We only support the IAccessibleEx interface on Windows 8 and above. This | 1144 // We only support the IAccessibleEx interface on Windows 8 and above. This |
| 1084 // is needed for the On screen Keyboard to show up in metro mode, when the | 1145 // is needed for the On screen Keyboard to show up in metro mode, when the |
| 1085 // user taps an editable region in the window. | 1146 // user taps an editable region in the window. |
| 1086 // All methods in the IAccessibleEx interface are unimplemented. | 1147 // All methods in the IAccessibleEx interface are unimplemented. |
| 1087 if (riid == IID_IAccessibleEx && | 1148 if (riid == IID_IAccessibleEx && |
| 1088 base::win::GetVersion() >= base::win::VERSION_WIN8) { | 1149 base::win::GetVersion() >= base::win::VERSION_WIN8) { |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1405 if (!child_widget->IsVisible()) | 1466 if (!child_widget->IsVisible()) |
| 1406 continue; | 1467 continue; |
| 1407 | 1468 |
| 1408 if (widget->GetNativeWindowProperty(kWidgetNativeViewHostKey)) | 1469 if (widget->GetNativeWindowProperty(kWidgetNativeViewHostKey)) |
| 1409 continue; | 1470 continue; |
| 1410 | 1471 |
| 1411 result_child_widgets->push_back(child_widget); | 1472 result_child_widgets->push_back(child_widget); |
| 1412 } | 1473 } |
| 1413 } | 1474 } |
| 1414 | 1475 |
| 1476 void NativeViewAccessibilityWin::AddAlertTarget() { | |
| 1477 ViewStorage* view_storage = ViewStorage::GetInstance(); | |
| 1478 for (size_t i = 0; i < alert_target_view_storage_ids_.size(); ++i) { | |
| 1479 int view_storage_id = alert_target_view_storage_ids_[i]; | |
| 1480 View* view = view_storage->RetrieveView(view_storage_id); | |
| 1481 if (view == view_) | |
| 1482 return; | |
| 1483 } | |
| 1484 int view_storage_id = view_storage->CreateStorageID(); | |
| 1485 view_storage->StoreView(view_storage_id, view_); | |
| 1486 alert_target_view_storage_ids_.push_back(view_storage_id); | |
| 1487 } | |
| 1488 | |
| 1489 void NativeViewAccessibilityWin::RemoveAlertTarget() { | |
| 1490 ViewStorage* view_storage = ViewStorage::GetInstance(); | |
| 1491 size_t i = 0; | |
| 1492 while (i < alert_target_view_storage_ids_.size()) { | |
| 1493 int view_storage_id = alert_target_view_storage_ids_[i]; | |
| 1494 View* view = view_storage->RetrieveView(view_storage_id); | |
| 1495 if (view == NULL || view == view_) { | |
| 1496 alert_target_view_storage_ids_.erase( | |
|
David Tseng
2014/05/08 17:53:42
When would you add a view == NULL?
dmazzoni
2014/05/08 19:16:13
We're using ViewStorage, which automatically nulls
| |
| 1497 alert_target_view_storage_ids_.begin() + i); | |
| 1498 } else { | |
| 1499 ++i; | |
| 1500 } | |
| 1501 } | |
| 1502 } | |
| 1503 | |
| 1415 } // namespace views | 1504 } // namespace views |
| OLD | NEW |