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

Side by Side Diff: ui/accessibility/platform/ax_platform_node_mac.mm

Issue 2016243002: Mac a11y: Add RoleDescription and Value attributes to accessibility information. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address review comments. Created 4 years, 6 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 #import "ui/accessibility/platform/ax_platform_node_mac.h" 5 #import "ui/accessibility/platform/ax_platform_node_mac.h"
6 6
7 #import <Cocoa/Cocoa.h> 7 #import <Cocoa/Cocoa.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include "base/macros.h" 10 #include "base/macros.h"
11 #include "base/strings/sys_string_conversions.h" 11 #include "base/strings/sys_string_conversions.h"
12 #import "ui/accessibility/ax_node_data.h" 12 #import "ui/accessibility/ax_node_data.h"
13 #include "ui/accessibility/ax_view_state.h"
13 #import "ui/accessibility/platform/ax_platform_node_delegate.h" 14 #import "ui/accessibility/platform/ax_platform_node_delegate.h"
14 #import "ui/gfx/mac/coordinate_conversion.h" 15 #import "ui/gfx/mac/coordinate_conversion.h"
15 16
16 namespace { 17 namespace {
17 18
18 struct MapEntry { 19 struct MapEntry {
19 ui::AXRole value; 20 ui::AXRole value;
20 NSString* nativeValue; 21 NSString* nativeValue;
21 }; 22 };
22 23
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 }; 184 };
184 185
185 RoleMap subrole_map; 186 RoleMap subrole_map;
186 for (size_t i = 0; i < arraysize(subroles); ++i) 187 for (size_t i = 0; i < arraysize(subroles); ++i)
187 subrole_map[subroles[i].value] = subroles[i].nativeValue; 188 subrole_map[subroles[i].value] = subroles[i].nativeValue;
188 return subrole_map; 189 return subrole_map;
189 } 190 }
190 191
191 } // namespace 192 } // namespace
192 193
194 @interface AXPlatformNodeCocoa ()
195 // Helper function for string attributes that don't require extra processing.
196 - (NSString*)getStringAttribute:(ui::AXStringAttribute)attribute;
197 @end
198
193 @implementation AXPlatformNodeCocoa 199 @implementation AXPlatformNodeCocoa
194 200
195 // A mapping of AX roles to native roles. 201 // A mapping of AX roles to native roles.
196 + (NSString*)nativeRoleFromAXRole:(ui::AXRole)role { 202 + (NSString*)nativeRoleFromAXRole:(ui::AXRole)role {
197 CR_DEFINE_STATIC_LOCAL(RoleMap, role_map, (BuildRoleMap())); 203 CR_DEFINE_STATIC_LOCAL(RoleMap, role_map, (BuildRoleMap()));
198 RoleMap::iterator it = role_map.find(role); 204 RoleMap::iterator it = role_map.find(role);
199 return it != role_map.end() ? it->second : NSAccessibilityUnknownRole; 205 return it != role_map.end() ? it->second : NSAccessibilityUnknownRole;
200 } 206 }
201 207
202 // A mapping of AX roles to native subroles. 208 // A mapping of AX roles to native subroles.
(...skipping 13 matching lines...) Expand all
216 - (void)detach { 222 - (void)detach {
217 node_ = nil; 223 node_ = nil;
218 } 224 }
219 225
220 - (NSRect)boundsInScreen { 226 - (NSRect)boundsInScreen {
221 if (!node_) 227 if (!node_)
222 return NSZeroRect; 228 return NSZeroRect;
223 return gfx::ScreenRectToNSRect(node_->GetBoundsInScreen()); 229 return gfx::ScreenRectToNSRect(node_->GetBoundsInScreen());
224 } 230 }
225 231
232 - (NSString*)getStringAttribute:(ui::AXStringAttribute)attribute {
233 std::string attributeValue;
234 if (node_->GetStringAttribute(attribute, &attributeValue))
235 return base::SysUTF8ToNSString(attributeValue);
236 return nil;
237 }
238
239 // NSAccessibility informal protocol implementation.
240
241 - (BOOL)accessibilityIsIgnored {
242 return [[self AXRole] isEqualToString:NSAccessibilityUnknownRole];
243 }
244
245 - (id)accessibilityHitTest:(NSPoint)point {
246 for (AXPlatformNodeCocoa* child in [self AXChildren]) {
247 if (NSPointInRect(point, child.boundsInScreen))
248 return [child accessibilityHitTest:point];
249 }
250 return NSAccessibilityUnignoredAncestor(self);
251 }
252
253 - (NSArray*)accessibilityActionNames {
254 return nil;
255 }
256
257 - (NSArray*)accessibilityAttributeNames {
258 // These attributes are required on all accessibility objects.
259 NSMutableArray* axAttributes = [NSMutableArray
tapted 2016/06/10 03:17:17 we should keep the array literals as constants. E.
Patti Lor 2016/06/16 07:05:21 Done. Thanks for the const tip, I hadn't known abo
260 arrayWithObjects:NSAccessibilityChildrenAttribute,
261 NSAccessibilityParentAttribute,
262 NSAccessibilityPositionAttribute,
263 NSAccessibilityRoleAttribute,
264 NSAccessibilitySizeAttribute,
265 NSAccessibilitySubroleAttribute,
266
267 // Title is required for most elements.
268 // Cocoa asks for the value even if it
269 // is omitted here, but won't present it
270 // to accessibility APIs without this.
271 NSAccessibilityTitleAttribute,
272
273 // Attributes which are not required, but
274 // are general to all roles.
275 NSAccessibilityRoleDescriptionAttribute, nil];
276 switch (node_->GetData().role) {
277 case ui::AX_ROLE_CHECK_BOX:
278 case ui::AX_ROLE_COMBO_BOX:
279 case ui::AX_ROLE_MENU_ITEM_CHECK_BOX:
280 case ui::AX_ROLE_MENU_ITEM_RADIO:
281 case ui::AX_ROLE_RADIO_BUTTON:
282 case ui::AX_ROLE_SEARCH_BOX:
283 case ui::AX_ROLE_SLIDER:
284 case ui::AX_ROLE_SLIDER_THUMB:
285 case ui::AX_ROLE_TOGGLE_BUTTON:
286 case ui::AX_ROLE_TEXT_FIELD:
287 [axAttributes addObjectsFromArray:@[ NSAccessibilityValueAttribute ]];
288 break;
289 // TODO(tapted): Add additional attributes based on role.
290 default:
291 break;
292 }
293 return axAttributes;
294 }
295
296 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute {
297 return NO;
298 }
299
300 - (id)accessibilityAttributeValue:(NSString*)attribute {
301 SEL selector = NSSelectorFromString(attribute);
302 if ([self respondsToSelector:selector])
303 return [self performSelector:selector];
304 return nil;
305 }
306
307 // NSAccessibility attributes.
308
226 - (NSArray*)AXChildren { 309 - (NSArray*)AXChildren {
227 if (!node_) 310 if (!node_)
228 return nil; 311 return nil;
229 int count = node_->GetChildCount(); 312 int count = node_->GetChildCount();
230 NSMutableArray* children = [NSMutableArray arrayWithCapacity:count]; 313 NSMutableArray* children = [NSMutableArray arrayWithCapacity:count];
231 for (int i = 0; i < count; ++i) 314 for (int i = 0; i < count; ++i)
232 [children addObject:node_->ChildAtIndex(i)]; 315 [children addObject:node_->ChildAtIndex(i)];
233 return NSAccessibilityUnignoredChildren(children); 316 return NSAccessibilityUnignoredChildren(children);
234 } 317 }
235 318
(...skipping 10 matching lines...) Expand all
246 - (NSString*)AXRole { 329 - (NSString*)AXRole {
247 if (!node_) 330 if (!node_)
248 return nil; 331 return nil;
249 return [[self class] nativeRoleFromAXRole:node_->GetData().role]; 332 return [[self class] nativeRoleFromAXRole:node_->GetData().role];
250 } 333 }
251 334
252 - (NSValue*)AXSize { 335 - (NSValue*)AXSize {
253 return [NSValue valueWithSize:self.boundsInScreen.size]; 336 return [NSValue valueWithSize:self.boundsInScreen.size];
254 } 337 }
255 338
256 - (NSString*)AXTitle { 339 - (NSString*)AXSubrole {
257 std::string value; 340 ui::AXRole role = node_->GetData().role;
258 if (node_->GetStringAttribute(ui::AX_ATTR_NAME, &value)) 341 switch (role) {
259 return base::SysUTF8ToNSString(value); 342 case ui::AX_ROLE_TEXT_FIELD: {
260 return nil; 343 if (ui::AXViewState::HasStateFlag(node_->GetData().state,
344 ui::AX_STATE_PROTECTED)) {
345 return NSAccessibilitySecureTextFieldSubrole;
346 }
347 } break;
tapted 2016/06/10 03:17:17 break would go inside the curlies, but I don't thi
Patti Lor 2016/06/16 07:05:21 Done.
348 default:
349 break;
350 }
351 return [AXPlatformNodeCocoa nativeSubroleFromAXRole:role];
261 } 352 }
262 353
263 // NSAccessibility informal protocol implementation. 354 - (NSString*)AXTitle {
264 355 return [self getStringAttribute:ui::AX_ATTR_NAME];
265 - (BOOL)accessibilityIsIgnored {
266 return [[self AXRole] isEqualToString:NSAccessibilityUnknownRole];
267 } 356 }
268 357
269 - (id)accessibilityHitTest:(NSPoint)point { 358 - (NSString*)AXRoleDescription {
270 for (AXPlatformNodeCocoa* child in [self AXChildren]) { 359 NSString* description = [self getStringAttribute:ui::AX_ATTR_DESCRIPTION];
271 if (NSPointInRect(point, child.boundsInScreen)) 360 if (!description)
272 return [child accessibilityHitTest:point]; 361 return NSAccessibilityRoleDescription([self AXRole], [self AXSubrole]);
273 } 362 return description;
274 return NSAccessibilityUnignoredAncestor(self);
275 } 363 }
276 364
277 - (NSArray*)accessibilityActionNames { 365 - (NSString*)AXValue {
278 return nil; 366 return [self getStringAttribute:ui::AX_ATTR_VALUE];
279 }
280
281 - (NSArray*)accessibilityAttributeNames {
282 // These attributes are required on all accessibility objects.
283 return @[
284 NSAccessibilityChildrenAttribute,
285 NSAccessibilityParentAttribute,
286 NSAccessibilityPositionAttribute,
287 NSAccessibilityRoleAttribute,
288 NSAccessibilitySizeAttribute,
289
290 // Title is required for most elements. Cocoa asks for the value even if it
291 // is omitted here, but won't present it to accessibility APIs without this.
292 NSAccessibilityTitleAttribute,
293 ];
294 // TODO(tapted): Add additional attributes based on role.
295 }
296
297 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute {
298 return NO;
299 }
300
301 - (id)accessibilityAttributeValue:(NSString*)attribute {
302 SEL selector = NSSelectorFromString(attribute);
303 if ([self respondsToSelector:selector])
304 return [self performSelector:selector];
305 return nil;
306 } 367 }
307 368
308 @end 369 @end
309 370
310 namespace ui { 371 namespace ui {
311 372
312 // static 373 // static
313 AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) { 374 AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) {
314 AXPlatformNodeBase* node = new AXPlatformNodeMac(); 375 AXPlatformNodeBase* node = new AXPlatformNodeMac();
315 node->Init(delegate); 376 node->Init(delegate);
(...skipping 21 matching lines...) Expand all
337 void AXPlatformNodeMac::NotifyAccessibilityEvent(ui::AXEvent event_type) { 398 void AXPlatformNodeMac::NotifyAccessibilityEvent(ui::AXEvent event_type) {
338 // TODO(dmazzoni): implement this. http://crbug.com/396137 399 // TODO(dmazzoni): implement this. http://crbug.com/396137
339 } 400 }
340 401
341 int AXPlatformNodeMac::GetIndexInParent() { 402 int AXPlatformNodeMac::GetIndexInParent() {
342 // TODO(dmazzoni): implement this. http://crbug.com/396137 403 // TODO(dmazzoni): implement this. http://crbug.com/396137
343 return -1; 404 return -1;
344 } 405 }
345 406
346 } // namespace ui 407 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698