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 |