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

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
« no previous file with comments | « ui/accessibility/ax_view_state.cc ('k') | ui/views/views.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #include "ui/accessibility/ax_node_data.h"
13 #import "ui/accessibility/platform/ax_platform_node_delegate.h" 13 #include "ui/accessibility/ax_view_state.h"
14 #include "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
23 typedef std::map<ui::AXRole, NSString*> RoleMap; 24 typedef std::map<ui::AXRole, NSString*> RoleMap;
(...skipping 159 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
226 - (NSArray*)AXChildren { 232 - (NSString*)getStringAttribute:(ui::AXStringAttribute)attribute {
227 if (!node_) 233 std::string attributeValue;
228 return nil; 234 if (node_->GetStringAttribute(attribute, &attributeValue))
229 int count = node_->GetChildCount(); 235 return base::SysUTF8ToNSString(attributeValue);
230 NSMutableArray* children = [NSMutableArray arrayWithCapacity:count];
231 for (int i = 0; i < count; ++i)
232 [children addObject:node_->ChildAtIndex(i)];
233 return NSAccessibilityUnignoredChildren(children);
234 }
235
236 - (id)AXParent {
237 if (!node_)
238 return nil;
239 return NSAccessibilityUnignoredAncestor(node_->GetParent());
240 }
241
242 - (NSValue*)AXPosition {
243 return [NSValue valueWithPoint:self.boundsInScreen.origin];
244 }
245
246 - (NSString*)AXRole {
247 if (!node_)
248 return nil;
249 return [[self class] nativeRoleFromAXRole:node_->GetData().role];
250 }
251
252 - (NSValue*)AXSize {
253 return [NSValue valueWithSize:self.boundsInScreen.size];
254 }
255
256 - (NSString*)AXTitle {
257 std::string value;
258 if (node_->GetStringAttribute(ui::AX_ATTR_NAME, &value))
259 return base::SysUTF8ToNSString(value);
260 return nil; 236 return nil;
261 } 237 }
262 238
263 // NSAccessibility informal protocol implementation. 239 // NSAccessibility informal protocol implementation.
264 240
265 - (BOOL)accessibilityIsIgnored { 241 - (BOOL)accessibilityIsIgnored {
266 return [[self AXRole] isEqualToString:NSAccessibilityUnknownRole]; 242 return [[self AXRole] isEqualToString:NSAccessibilityUnknownRole];
267 } 243 }
268 244
269 - (id)accessibilityHitTest:(NSPoint)point { 245 - (id)accessibilityHitTest:(NSPoint)point {
270 for (AXPlatformNodeCocoa* child in [self AXChildren]) { 246 for (AXPlatformNodeCocoa* child in [self AXChildren]) {
271 if (NSPointInRect(point, child.boundsInScreen)) 247 if (NSPointInRect(point, child.boundsInScreen))
272 return [child accessibilityHitTest:point]; 248 return [child accessibilityHitTest:point];
273 } 249 }
274 return NSAccessibilityUnignoredAncestor(self); 250 return NSAccessibilityUnignoredAncestor(self);
275 } 251 }
276 252
277 - (NSArray*)accessibilityActionNames { 253 - (NSArray*)accessibilityActionNames {
278 return nil; 254 return nil;
279 } 255 }
280 256
281 - (NSArray*)accessibilityAttributeNames { 257 - (NSArray*)accessibilityAttributeNames {
282 // These attributes are required on all accessibility objects. 258 // These attributes are required on all accessibility objects.
283 return @[ 259 NSArray* const kAllRoleAttributes = @[
284 NSAccessibilityChildrenAttribute, 260 NSAccessibilityChildrenAttribute,
285 NSAccessibilityParentAttribute, 261 NSAccessibilityParentAttribute,
286 NSAccessibilityPositionAttribute, 262 NSAccessibilityPositionAttribute,
287 NSAccessibilityRoleAttribute, 263 NSAccessibilityRoleAttribute,
288 NSAccessibilitySizeAttribute, 264 NSAccessibilitySizeAttribute,
265 NSAccessibilitySubroleAttribute,
289 266
290 // Title is required for most elements. Cocoa asks for the value even if it 267 // 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. 268 // is omitted here, but won't present it to accessibility APIs without this.
292 NSAccessibilityTitleAttribute, 269 NSAccessibilityTitleAttribute,
270
271 // Attributes which are not required, but are general to all roles.
272 NSAccessibilityRoleDescriptionAttribute,
293 ]; 273 ];
294 // TODO(tapted): Add additional attributes based on role. 274
275 // Attributes required for user-editable controls.
276 NSArray* const kValueAttributes = @[ NSAccessibilityValueAttribute ];
277
278 base::scoped_nsobject<NSMutableArray> axAttributes(
279 [[NSMutableArray alloc] init]);
280
281 [axAttributes addObjectsFromArray:kAllRoleAttributes];
282 switch (node_->GetData().role) {
283 case ui::AX_ROLE_CHECK_BOX:
284 case ui::AX_ROLE_COMBO_BOX:
285 case ui::AX_ROLE_MENU_ITEM_CHECK_BOX:
286 case ui::AX_ROLE_MENU_ITEM_RADIO:
287 case ui::AX_ROLE_RADIO_BUTTON:
288 case ui::AX_ROLE_SEARCH_BOX:
289 case ui::AX_ROLE_SLIDER:
290 case ui::AX_ROLE_SLIDER_THUMB:
291 case ui::AX_ROLE_TOGGLE_BUTTON:
292 case ui::AX_ROLE_TEXT_FIELD:
293 [axAttributes addObjectsFromArray:kValueAttributes];
294 break;
295 // TODO(tapted): Add additional attributes based on role.
296 default:
297 break;
298 }
299 return axAttributes.autorelease();
295 } 300 }
296 301
297 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute { 302 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute {
298 return NO; 303 return NO;
299 } 304 }
300 305
301 - (id)accessibilityAttributeValue:(NSString*)attribute { 306 - (id)accessibilityAttributeValue:(NSString*)attribute {
302 SEL selector = NSSelectorFromString(attribute); 307 SEL selector = NSSelectorFromString(attribute);
303 if ([self respondsToSelector:selector]) 308 if ([self respondsToSelector:selector])
304 return [self performSelector:selector]; 309 return [self performSelector:selector];
305 return nil; 310 return nil;
306 } 311 }
307 312
313 // NSAccessibility attributes.
314
315 - (NSArray*)AXChildren {
316 if (!node_)
317 return nil;
318 int count = node_->GetChildCount();
319 NSMutableArray* children = [NSMutableArray arrayWithCapacity:count];
320 for (int i = 0; i < count; ++i)
321 [children addObject:node_->ChildAtIndex(i)];
322 return NSAccessibilityUnignoredChildren(children);
323 }
324
325 - (id)AXParent {
326 if (!node_)
327 return nil;
328 return NSAccessibilityUnignoredAncestor(node_->GetParent());
329 }
330
331 - (NSValue*)AXPosition {
332 return [NSValue valueWithPoint:self.boundsInScreen.origin];
333 }
334
335 - (NSString*)AXRole {
336 if (!node_)
337 return nil;
338 return [[self class] nativeRoleFromAXRole:node_->GetData().role];
339 }
340
341 - (NSString*)AXSubrole {
342 ui::AXRole role = node_->GetData().role;
343 switch (role) {
344 case ui::AX_ROLE_TEXT_FIELD:
345 if (ui::AXViewState::IsFlagSet(node_->GetData().state,
346 ui::AX_STATE_PROTECTED))
347 return NSAccessibilitySecureTextFieldSubrole;
348 break;
349 default:
350 break;
351 }
352 return [AXPlatformNodeCocoa nativeSubroleFromAXRole:role];
353 }
354
355 - (NSString*)AXRoleDescription {
356 NSString* description = [self getStringAttribute:ui::AX_ATTR_DESCRIPTION];
357 if (!description)
358 return NSAccessibilityRoleDescription([self AXRole], [self AXSubrole]);
359 return description;
360 }
361
362 - (NSValue*)AXSize {
363 return [NSValue valueWithSize:self.boundsInScreen.size];
364 }
365
366 - (NSString*)AXTitle {
367 return [self getStringAttribute:ui::AX_ATTR_NAME];
368 }
369
370 - (NSString*)AXValue {
371 return [self getStringAttribute:ui::AX_ATTR_VALUE];
372 }
373
308 @end 374 @end
309 375
310 namespace ui { 376 namespace ui {
311 377
312 // static 378 // static
313 AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) { 379 AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) {
314 AXPlatformNodeBase* node = new AXPlatformNodeMac(); 380 AXPlatformNodeBase* node = new AXPlatformNodeMac();
315 node->Init(delegate); 381 node->Init(delegate);
316 return node; 382 return node;
317 } 383 }
(...skipping 19 matching lines...) Expand all
337 void AXPlatformNodeMac::NotifyAccessibilityEvent(ui::AXEvent event_type) { 403 void AXPlatformNodeMac::NotifyAccessibilityEvent(ui::AXEvent event_type) {
338 // TODO(dmazzoni): implement this. http://crbug.com/396137 404 // TODO(dmazzoni): implement this. http://crbug.com/396137
339 } 405 }
340 406
341 int AXPlatformNodeMac::GetIndexInParent() { 407 int AXPlatformNodeMac::GetIndexInParent() {
342 // TODO(dmazzoni): implement this. http://crbug.com/396137 408 // TODO(dmazzoni): implement this. http://crbug.com/396137
343 return -1; 409 return -1;
344 } 410 }
345 411
346 } // namespace ui 412 } // namespace ui
OLDNEW
« no previous file with comments | « ui/accessibility/ax_view_state.cc ('k') | ui/views/views.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698