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 if (!targets || !n_targets) |
| 883 return E_INVALIDARG; |
| 884 |
| 885 *n_targets = 0; |
| 886 *targets = NULL; |
| 887 |
| 888 // Only respond to requests for relations of type "alerts" on the |
| 889 // root view. |
| 890 base::string16 type(type_bstr); |
| 891 if (type != L"alerts" || view_->parent()) |
| 892 return S_FALSE; |
| 893 |
| 894 // Collect all of the alert views that are still valid. |
| 895 std::vector<View*> alert_views; |
| 896 ViewStorage* view_storage = ViewStorage::GetInstance(); |
| 897 for (size_t i = 0; i < alert_target_view_storage_ids_.size(); ++i) { |
| 898 int view_storage_id = alert_target_view_storage_ids_[i]; |
| 899 View* view = view_storage->RetrieveView(view_storage_id); |
| 900 if (!view || !view_->Contains(view)) |
| 901 continue; |
| 902 alert_views.push_back(view); |
| 903 } |
| 904 |
| 905 long count = alert_views.size(); |
| 906 if (count == 0) |
| 907 return S_FALSE; |
| 908 |
| 909 // Don't return more targets than max_targets - but note that the caller |
| 910 // is allowed to specify max_targets=0 to mean no limit. |
| 911 if (max_targets > 0 && count > max_targets) |
| 912 count = max_targets; |
| 913 |
| 914 // Return the number of targets. |
| 915 *n_targets = count; |
| 916 |
| 917 // Allocate COM memory for the result array and populate it. |
| 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 return S_OK; |
| 925 } |
| 926 |
868 // | 927 // |
869 // IAccessibleText | 928 // IAccessibleText |
870 // | 929 // |
871 | 930 |
872 STDMETHODIMP NativeViewAccessibilityWin::get_nCharacters(LONG* n_characters) { | 931 STDMETHODIMP NativeViewAccessibilityWin::get_nCharacters(LONG* n_characters) { |
873 if (!view_) | 932 if (!view_) |
874 return E_FAIL; | 933 return E_FAIL; |
875 | 934 |
876 if (!n_characters) | 935 if (!n_characters) |
877 return E_INVALIDARG; | 936 return E_INVALIDARG; |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1064 | 1123 |
1065 // | 1124 // |
1066 // IServiceProvider methods. | 1125 // IServiceProvider methods. |
1067 // | 1126 // |
1068 | 1127 |
1069 STDMETHODIMP NativeViewAccessibilityWin::QueryService( | 1128 STDMETHODIMP NativeViewAccessibilityWin::QueryService( |
1070 REFGUID guidService, REFIID riid, void** object) { | 1129 REFGUID guidService, REFIID riid, void** object) { |
1071 if (!view_) | 1130 if (!view_) |
1072 return E_FAIL; | 1131 return E_FAIL; |
1073 | 1132 |
1074 if (riid == IID_IAccessible2) | 1133 if (riid == IID_IAccessible2 || riid == IID_IAccessible2_2) |
1075 AccessibleWebViewRegistry::GetInstance()->EnableIAccessible2Support(); | 1134 AccessibleWebViewRegistry::GetInstance()->EnableIAccessible2Support(); |
1076 | 1135 |
1077 if (guidService == IID_IAccessible || | 1136 if (guidService == IID_IAccessible || |
1078 guidService == IID_IAccessible2 || | 1137 guidService == IID_IAccessible2 || |
| 1138 guidService == IID_IAccessible2_2 || |
1079 guidService == IID_IAccessibleText) { | 1139 guidService == IID_IAccessibleText) { |
1080 return QueryInterface(riid, object); | 1140 return QueryInterface(riid, object); |
1081 } | 1141 } |
1082 | 1142 |
1083 // We only support the IAccessibleEx interface on Windows 8 and above. This | 1143 // 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 | 1144 // is needed for the On screen Keyboard to show up in metro mode, when the |
1085 // user taps an editable region in the window. | 1145 // user taps an editable region in the window. |
1086 // All methods in the IAccessibleEx interface are unimplemented. | 1146 // All methods in the IAccessibleEx interface are unimplemented. |
1087 if (riid == IID_IAccessibleEx && | 1147 if (riid == IID_IAccessibleEx && |
1088 base::win::GetVersion() >= base::win::VERSION_WIN8) { | 1148 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()) | 1465 if (!child_widget->IsVisible()) |
1406 continue; | 1466 continue; |
1407 | 1467 |
1408 if (widget->GetNativeWindowProperty(kWidgetNativeViewHostKey)) | 1468 if (widget->GetNativeWindowProperty(kWidgetNativeViewHostKey)) |
1409 continue; | 1469 continue; |
1410 | 1470 |
1411 result_child_widgets->push_back(child_widget); | 1471 result_child_widgets->push_back(child_widget); |
1412 } | 1472 } |
1413 } | 1473 } |
1414 | 1474 |
| 1475 void NativeViewAccessibilityWin::AddAlertTarget() { |
| 1476 ViewStorage* view_storage = ViewStorage::GetInstance(); |
| 1477 for (size_t i = 0; i < alert_target_view_storage_ids_.size(); ++i) { |
| 1478 int view_storage_id = alert_target_view_storage_ids_[i]; |
| 1479 View* view = view_storage->RetrieveView(view_storage_id); |
| 1480 if (view == view_) |
| 1481 return; |
| 1482 } |
| 1483 int view_storage_id = view_storage->CreateStorageID(); |
| 1484 view_storage->StoreView(view_storage_id, view_); |
| 1485 alert_target_view_storage_ids_.push_back(view_storage_id); |
| 1486 } |
| 1487 |
| 1488 void NativeViewAccessibilityWin::RemoveAlertTarget() { |
| 1489 ViewStorage* view_storage = ViewStorage::GetInstance(); |
| 1490 size_t i = 0; |
| 1491 while (i < alert_target_view_storage_ids_.size()) { |
| 1492 int view_storage_id = alert_target_view_storage_ids_[i]; |
| 1493 View* view = view_storage->RetrieveView(view_storage_id); |
| 1494 if (view == NULL || view == view_) { |
| 1495 alert_target_view_storage_ids_.erase( |
| 1496 alert_target_view_storage_ids_.begin() + i); |
| 1497 } else { |
| 1498 ++i; |
| 1499 } |
| 1500 } |
| 1501 } |
| 1502 |
1415 } // namespace views | 1503 } // namespace views |
OLD | NEW |