Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1340)

Side by Side Diff: ui/views/accessibility/native_view_accessibility_win.cc

Issue 266963002: Expose an accessible relation between the main window and active alert. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@ia2_1-3
Patch Set: Now with unit test Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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 if (targets) {
David Tseng 2014/05/13 01:34:54 Didn't you check this above?
dmazzoni 2014/05/13 07:38:46 Done.
919 *targets = static_cast<IUnknown**>(
920 CoTaskMemAlloc(count * sizeof(IUnknown*)));
921 for (long i = 0; i < count; ++i) {
922 (*targets)[i] = alert_views[i]->GetNativeViewAccessible();
923 (*targets)[i]->AddRef();
924 }
925 }
926 return S_OK;
927 }
928
868 // 929 //
869 // IAccessibleText 930 // IAccessibleText
870 // 931 //
871 932
872 STDMETHODIMP NativeViewAccessibilityWin::get_nCharacters(LONG* n_characters) { 933 STDMETHODIMP NativeViewAccessibilityWin::get_nCharacters(LONG* n_characters) {
873 if (!view_) 934 if (!view_)
874 return E_FAIL; 935 return E_FAIL;
875 936
876 if (!n_characters) 937 if (!n_characters)
877 return E_INVALIDARG; 938 return E_INVALIDARG;
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
1064 1125
1065 // 1126 //
1066 // IServiceProvider methods. 1127 // IServiceProvider methods.
1067 // 1128 //
1068 1129
1069 STDMETHODIMP NativeViewAccessibilityWin::QueryService( 1130 STDMETHODIMP NativeViewAccessibilityWin::QueryService(
1070 REFGUID guidService, REFIID riid, void** object) { 1131 REFGUID guidService, REFIID riid, void** object) {
1071 if (!view_) 1132 if (!view_)
1072 return E_FAIL; 1133 return E_FAIL;
1073 1134
1074 if (riid == IID_IAccessible2) 1135 if (riid == IID_IAccessible2 || riid == IID_IAccessible2_2)
1075 AccessibleWebViewRegistry::GetInstance()->EnableIAccessible2Support(); 1136 AccessibleWebViewRegistry::GetInstance()->EnableIAccessible2Support();
1076 1137
1077 if (guidService == IID_IAccessible || 1138 if (guidService == IID_IAccessible ||
1078 guidService == IID_IAccessible2 || 1139 guidService == IID_IAccessible2 ||
1140 guidService == IID_IAccessible2_2 ||
1079 guidService == IID_IAccessibleText) { 1141 guidService == IID_IAccessibleText) {
1080 return QueryInterface(riid, object); 1142 return QueryInterface(riid, object);
1081 } 1143 }
1082 1144
1083 // We only support the IAccessibleEx interface on Windows 8 and above. This 1145 // 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 1146 // is needed for the On screen Keyboard to show up in metro mode, when the
1085 // user taps an editable region in the window. 1147 // user taps an editable region in the window.
1086 // All methods in the IAccessibleEx interface are unimplemented. 1148 // All methods in the IAccessibleEx interface are unimplemented.
1087 if (riid == IID_IAccessibleEx && 1149 if (riid == IID_IAccessibleEx &&
1088 base::win::GetVersion() >= base::win::VERSION_WIN8) { 1150 base::win::GetVersion() >= base::win::VERSION_WIN8) {
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
1405 if (!child_widget->IsVisible()) 1467 if (!child_widget->IsVisible())
1406 continue; 1468 continue;
1407 1469
1408 if (widget->GetNativeWindowProperty(kWidgetNativeViewHostKey)) 1470 if (widget->GetNativeWindowProperty(kWidgetNativeViewHostKey))
1409 continue; 1471 continue;
1410 1472
1411 result_child_widgets->push_back(child_widget); 1473 result_child_widgets->push_back(child_widget);
1412 } 1474 }
1413 } 1475 }
1414 1476
1477 void NativeViewAccessibilityWin::AddAlertTarget() {
1478 ViewStorage* view_storage = ViewStorage::GetInstance();
1479 for (size_t i = 0; i < alert_target_view_storage_ids_.size(); ++i) {
1480 int view_storage_id = alert_target_view_storage_ids_[i];
1481 View* view = view_storage->RetrieveView(view_storage_id);
1482 if (view == view_)
1483 return;
1484 }
1485 int view_storage_id = view_storage->CreateStorageID();
1486 view_storage->StoreView(view_storage_id, view_);
1487 alert_target_view_storage_ids_.push_back(view_storage_id);
1488 }
1489
1490 void NativeViewAccessibilityWin::RemoveAlertTarget() {
1491 ViewStorage* view_storage = ViewStorage::GetInstance();
1492 size_t i = 0;
1493 while (i < alert_target_view_storage_ids_.size()) {
1494 int view_storage_id = alert_target_view_storage_ids_[i];
1495 View* view = view_storage->RetrieveView(view_storage_id);
1496 if (view == NULL || view == view_) {
1497 alert_target_view_storage_ids_.erase(
1498 alert_target_view_storage_ids_.begin() + i);
David Tseng 2014/05/13 01:34:54 break? (since you're never duplicating ids) on ins
David Tseng 2014/05/13 13:47:11 FYI (unresolved comment); not really a big deal si
dmazzoni 2014/05/13 15:52:44 Sorry, forgot to respond. I don't want to break be
1499 } else {
1500 ++i;
1501 }
1502 }
1503 }
1504
1415 } // namespace views 1505 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698