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

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

Issue 420653003: MacViews: Accessibility bridge (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 2nd draft, based on 423513005 Created 6 years, 4 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 | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #import "ui/accessibility/platform/ax_platform_node_mac.h"
6
7 #import <Cocoa/Cocoa.h>
8
9 #include "base/strings/sys_string_conversions.h"
10 #import "ui/accessibility/platform/ax_platform_node_delegate.h"
11 #import "ui/gfx/mac/coordinate_conversion.h"
12
13 namespace {
14
15 struct MapEntry {
16 ui::AXRole value;
17 NSString* nativeValue;
18 };
19
20 typedef std::map<ui::AXRole, NSString*> RoleMap;
21
22 RoleMap BuildRoleMap() {
23 const MapEntry roles[] = {
24 {ui::AX_ROLE_ALERT, NSAccessibilityGroupRole},
25 {ui::AX_ROLE_ALERT_DIALOG, NSAccessibilityGroupRole},
26 {ui::AX_ROLE_ANNOTATION, NSAccessibilityUnknownRole},
27 {ui::AX_ROLE_APPLICATION, NSAccessibilityGroupRole},
28 {ui::AX_ROLE_ARTICLE, NSAccessibilityGroupRole},
29 {ui::AX_ROLE_BANNER, NSAccessibilityGroupRole},
30 {ui::AX_ROLE_BROWSER, NSAccessibilityBrowserRole},
31 {ui::AX_ROLE_BUSY_INDICATOR, NSAccessibilityBusyIndicatorRole},
32 {ui::AX_ROLE_BUTTON, NSAccessibilityButtonRole},
33 {ui::AX_ROLE_CANVAS, NSAccessibilityImageRole},
34 {ui::AX_ROLE_CELL, @"AXCell"},
35 {ui::AX_ROLE_CHECK_BOX, NSAccessibilityCheckBoxRole},
36 {ui::AX_ROLE_COLOR_WELL, NSAccessibilityColorWellRole},
37 {ui::AX_ROLE_COLUMN, NSAccessibilityColumnRole},
38 {ui::AX_ROLE_COLUMN_HEADER, @"AXCell"},
39 {ui::AX_ROLE_COMBO_BOX, NSAccessibilityComboBoxRole},
40 {ui::AX_ROLE_COMPLEMENTARY, NSAccessibilityGroupRole},
41 {ui::AX_ROLE_CONTENT_INFO, NSAccessibilityGroupRole},
42 {ui::AX_ROLE_DEFINITION, NSAccessibilityGroupRole},
43 {ui::AX_ROLE_DESCRIPTION_LIST_DETAIL, NSAccessibilityGroupRole},
44 {ui::AX_ROLE_DESCRIPTION_LIST_TERM, NSAccessibilityGroupRole},
45 {ui::AX_ROLE_DIALOG, NSAccessibilityGroupRole},
46 {ui::AX_ROLE_DIRECTORY, NSAccessibilityListRole},
47 {ui::AX_ROLE_DISCLOSURE_TRIANGLE, NSAccessibilityDisclosureTriangleRole},
48 {ui::AX_ROLE_DIV, NSAccessibilityGroupRole},
49 {ui::AX_ROLE_DOCUMENT, NSAccessibilityGroupRole},
50 {ui::AX_ROLE_DRAWER, NSAccessibilityDrawerRole},
51 {ui::AX_ROLE_EDITABLE_TEXT, NSAccessibilityTextFieldRole},
52 {ui::AX_ROLE_FOOTER, NSAccessibilityGroupRole},
53 {ui::AX_ROLE_FORM, NSAccessibilityGroupRole},
54 {ui::AX_ROLE_GRID, NSAccessibilityGridRole},
55 {ui::AX_ROLE_GROUP, NSAccessibilityGroupRole},
56 {ui::AX_ROLE_GROW_AREA, NSAccessibilityGrowAreaRole},
57 {ui::AX_ROLE_HEADING, @"AXHeading"},
58 {ui::AX_ROLE_HELP_TAG, NSAccessibilityHelpTagRole},
59 {ui::AX_ROLE_HORIZONTAL_RULE, NSAccessibilityGroupRole},
60 {ui::AX_ROLE_IFRAME, NSAccessibilityGroupRole},
61 {ui::AX_ROLE_IGNORED, NSAccessibilityUnknownRole},
62 {ui::AX_ROLE_IMAGE, NSAccessibilityImageRole},
63 {ui::AX_ROLE_IMAGE_MAP, NSAccessibilityGroupRole},
64 {ui::AX_ROLE_IMAGE_MAP_LINK, NSAccessibilityLinkRole},
65 {ui::AX_ROLE_INCREMENTOR, NSAccessibilityIncrementorRole},
66 {ui::AX_ROLE_LABEL_TEXT, NSAccessibilityGroupRole},
67 {ui::AX_ROLE_LINK, NSAccessibilityLinkRole},
68 {ui::AX_ROLE_LIST, NSAccessibilityListRole},
69 {ui::AX_ROLE_LIST_BOX, NSAccessibilityListRole},
70 {ui::AX_ROLE_LIST_BOX_OPTION, NSAccessibilityStaticTextRole},
71 {ui::AX_ROLE_LIST_ITEM, NSAccessibilityGroupRole},
72 {ui::AX_ROLE_LIST_MARKER, @"AXListMarker"},
73 {ui::AX_ROLE_LOG, NSAccessibilityGroupRole},
74 {ui::AX_ROLE_MAIN, NSAccessibilityGroupRole},
75 {ui::AX_ROLE_MARQUEE, NSAccessibilityGroupRole},
76 {ui::AX_ROLE_MATH, NSAccessibilityGroupRole},
77 {ui::AX_ROLE_MATTE, NSAccessibilityMatteRole},
78 {ui::AX_ROLE_MENU, NSAccessibilityMenuRole},
79 {ui::AX_ROLE_MENU_BAR, NSAccessibilityMenuBarRole},
80 {ui::AX_ROLE_MENU_BUTTON, NSAccessibilityButtonRole},
81 {ui::AX_ROLE_MENU_ITEM, NSAccessibilityMenuItemRole},
82 {ui::AX_ROLE_MENU_LIST_OPTION, NSAccessibilityMenuItemRole},
83 {ui::AX_ROLE_MENU_LIST_POPUP, NSAccessibilityUnknownRole},
84 {ui::AX_ROLE_NAVIGATION, NSAccessibilityGroupRole},
85 {ui::AX_ROLE_NOTE, NSAccessibilityGroupRole},
86 {ui::AX_ROLE_OUTLINE, NSAccessibilityOutlineRole},
87 {ui::AX_ROLE_PARAGRAPH, NSAccessibilityGroupRole},
88 {ui::AX_ROLE_POP_UP_BUTTON, NSAccessibilityPopUpButtonRole},
89 {ui::AX_ROLE_PRESENTATIONAL, NSAccessibilityGroupRole},
90 {ui::AX_ROLE_PROGRESS_INDICATOR, NSAccessibilityProgressIndicatorRole},
91 {ui::AX_ROLE_RADIO_BUTTON, NSAccessibilityRadioButtonRole},
92 {ui::AX_ROLE_RADIO_GROUP, NSAccessibilityRadioGroupRole},
93 {ui::AX_ROLE_REGION, NSAccessibilityGroupRole},
94 {ui::AX_ROLE_ROOT_WEB_AREA, @"AXWebArea"},
95 {ui::AX_ROLE_ROW, NSAccessibilityRowRole},
96 {ui::AX_ROLE_ROW_HEADER, @"AXCell"},
97 {ui::AX_ROLE_RULER, NSAccessibilityRulerRole},
98 {ui::AX_ROLE_RULER_MARKER, NSAccessibilityRulerMarkerRole},
99 {ui::AX_ROLE_SCROLL_BAR, NSAccessibilityScrollBarRole},
100 {ui::AX_ROLE_SEARCH, NSAccessibilityGroupRole},
101 {ui::AX_ROLE_SHEET, NSAccessibilitySheetRole},
102 {ui::AX_ROLE_SLIDER, NSAccessibilitySliderRole},
103 {ui::AX_ROLE_SLIDER_THUMB, NSAccessibilityValueIndicatorRole},
104 {ui::AX_ROLE_SPIN_BUTTON, NSAccessibilitySliderRole},
105 {ui::AX_ROLE_SPLITTER, NSAccessibilitySplitterRole},
106 {ui::AX_ROLE_SPLIT_GROUP, NSAccessibilitySplitGroupRole},
107 {ui::AX_ROLE_STATIC_TEXT, NSAccessibilityStaticTextRole},
108 {ui::AX_ROLE_STATUS, NSAccessibilityGroupRole},
109 {ui::AX_ROLE_SVG_ROOT, NSAccessibilityGroupRole},
110 {ui::AX_ROLE_SYSTEM_WIDE, NSAccessibilityUnknownRole},
111 {ui::AX_ROLE_TAB, NSAccessibilityRadioButtonRole},
112 {ui::AX_ROLE_TABLE, NSAccessibilityTableRole},
113 {ui::AX_ROLE_TABLE_HEADER_CONTAINER, NSAccessibilityGroupRole},
114 {ui::AX_ROLE_TAB_LIST, NSAccessibilityTabGroupRole},
115 {ui::AX_ROLE_TAB_PANEL, NSAccessibilityGroupRole},
116 {ui::AX_ROLE_TEXT_AREA, NSAccessibilityTextAreaRole},
117 {ui::AX_ROLE_TEXT_FIELD, NSAccessibilityTextFieldRole},
118 {ui::AX_ROLE_TIMER, NSAccessibilityGroupRole},
119 {ui::AX_ROLE_TOGGLE_BUTTON, NSAccessibilityCheckBoxRole},
120 {ui::AX_ROLE_TOOLBAR, NSAccessibilityToolbarRole},
121 {ui::AX_ROLE_TOOLTIP, NSAccessibilityGroupRole},
122 {ui::AX_ROLE_TREE, NSAccessibilityOutlineRole},
123 {ui::AX_ROLE_TREE_GRID, NSAccessibilityTableRole},
124 {ui::AX_ROLE_TREE_ITEM, NSAccessibilityRowRole},
125 {ui::AX_ROLE_VALUE_INDICATOR, NSAccessibilityValueIndicatorRole},
126 {ui::AX_ROLE_WEB_AREA, @"AXWebArea"},
127 {ui::AX_ROLE_WINDOW, NSAccessibilityWindowRole},
128
129 // TODO(dtseng): we don't correctly support the attributes for these
130 // roles.
131 // { ui::AX_ROLE_SCROLL_AREA, NSAccessibilityScrollAreaRole },
132 };
133
134 RoleMap role_map;
135 for (size_t i = 0; i < arraysize(roles); ++i)
136 role_map[roles[i].value] = roles[i].nativeValue;
137 return role_map;
138 }
139
140 RoleMap BuildSubroleMap() {
141 const MapEntry subroles[] = {
142 {ui::AX_ROLE_ALERT, @"AXApplicationAlert"},
143 {ui::AX_ROLE_ALERT_DIALOG, @"AXApplicationAlertDialog"},
144 {ui::AX_ROLE_ARTICLE, @"AXDocumentArticle"},
145 {ui::AX_ROLE_DEFINITION, @"AXDefinition"},
146 {ui::AX_ROLE_DESCRIPTION_LIST_DETAIL, @"AXDescription"},
147 {ui::AX_ROLE_DESCRIPTION_LIST_TERM, @"AXTerm"},
148 {ui::AX_ROLE_DIALOG, @"AXApplicationDialog"},
149 {ui::AX_ROLE_DOCUMENT, @"AXDocument"},
150 {ui::AX_ROLE_FOOTER, @"AXLandmarkContentInfo"},
151 {ui::AX_ROLE_APPLICATION, @"AXLandmarkApplication"},
152 {ui::AX_ROLE_BANNER, @"AXLandmarkBanner"},
153 {ui::AX_ROLE_COMPLEMENTARY, @"AXLandmarkComplementary"},
154 {ui::AX_ROLE_CONTENT_INFO, @"AXLandmarkContentInfo"},
155 {ui::AX_ROLE_MAIN, @"AXLandmarkMain"},
156 {ui::AX_ROLE_NAVIGATION, @"AXLandmarkNavigation"},
157 {ui::AX_ROLE_SEARCH, @"AXLandmarkSearch"},
158 {ui::AX_ROLE_LOG, @"AXApplicationLog"},
159 {ui::AX_ROLE_MARQUEE, @"AXApplicationMarquee"},
160 {ui::AX_ROLE_MATH, @"AXDocumentMath"},
161 {ui::AX_ROLE_NOTE, @"AXDocumentNote"},
162 {ui::AX_ROLE_REGION, @"AXDocumentRegion"},
163 {ui::AX_ROLE_STATUS, @"AXApplicationStatus"},
164 {ui::AX_ROLE_TAB_PANEL, @"AXTabPanel"},
165 {ui::AX_ROLE_TIMER, @"AXApplicationTimer"},
166 {ui::AX_ROLE_TOGGLE_BUTTON, @"AXToggleButton"},
167 {ui::AX_ROLE_TOOLTIP, @"AXUserInterfaceTooltip"},
168 {ui::AX_ROLE_TREE_ITEM, NSAccessibilityOutlineRowSubrole},
169 };
170
171 RoleMap subrole_map;
172 for (size_t i = 0; i < arraysize(subroles); ++i)
173 subrole_map[subroles[i].value] = subroles[i].nativeValue;
174 return subrole_map;
175 }
176
177 } // namespace
178
179 @implementation AXPlatformNodeCocoa
180
181 // A mapping of AX roles to native roles.
182 + (NSString*)nativeRoleFromAXRole:(ui::AXRole)role {
183 CR_DEFINE_STATIC_LOCAL(RoleMap, role_map, (BuildRoleMap()));
184 RoleMap::iterator it = role_map.find(role);
185 return it != role_map.end() ? it->second : NSAccessibilityUnknownRole;
186 }
187
188 // A mapping of AX roles to native subroles.
189 + (NSString*)nativeSubroleFromAXRole:(ui::AXRole)role {
190 CR_DEFINE_STATIC_LOCAL(RoleMap, subrole_map, (BuildSubroleMap()));
191 RoleMap::iterator it = subrole_map.find(role);
192 return it != subrole_map.end() ? it->second : nil;
193 }
194
195 - (instancetype)initWithNode:(ui::AXPlatformNode*)node {
196 if ((self = [super init])) {
197 node_ = node;
198 }
199 return self;
200 }
201
202 - (void)detach {
203 node_ = nil;
204 }
205
206 - (NSRect)boundsInScreen {
207 if (!node_)
208 return NSZeroRect;
209 return gfx::ScreenRectToNSRect(node_->GetBoundsInScreen());
210 }
211
212 - (BOOL)accessibilityIsIgnored {
213 return [[self AXRole] isEqualToString:NSAccessibilityUnknownRole];
214 }
215
216 - (id)accessibilityHitTest:(NSPoint)point {
217 for (AXPlatformNodeCocoa* child in [self AXChildren]) {
218 if (NSPointInRect(point, child.boundsInScreen))
219 return [child accessibilityHitTest:point];
220 }
221 return NSAccessibilityUnignoredAncestor(self);
222 }
223
224 - (NSArray*)accessibilityActionNames {
225 return nil;
226 }
227
228 - (NSArray*)accessibilityAttributeNames {
229 return @[
dmazzoni 2014/07/29 06:35:14 Cool, no wonder I didn't know about this, I just l
230 NSAccessibilityChildrenAttribute,
231 NSAccessibilityParentAttribute,
232 NSAccessibilityPositionAttribute,
233 NSAccessibilityRoleAttribute,
234 NSAccessibilitySizeAttribute,
235 NSAccessibilityTitleAttribute,
236 ];
237 }
238
239 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute {
240 return NO;
241 }
242
243 - (id)accessibilityAttributeValue:(NSString*)attribute {
244 SEL selector = NSSelectorFromString(attribute);
245 if ([self respondsToSelector:selector])
246 return [self performSelector:selector];
247 return nil;
248 }
249
250 - (NSArray*)AXChildren {
251 if (!node_)
252 return nil;
253 int count = node_->GetChildCount();
254 NSMutableArray* children = [NSMutableArray arrayWithCapacity:count];
255 for (int i = 0; i < count; ++i)
256 [children addObject:node_->ChildAtIndex(i)];
257 return NSAccessibilityUnignoredChildren(children);
258 }
259
260 - (id)AXParent {
261 if (!node_)
262 return nil;
263 return NSAccessibilityUnignoredAncestor(node_->GetParent());
264 }
265
266 - (NSValue*)AXPosition {
267 return [NSValue valueWithPoint:self.boundsInScreen.origin];
268 }
269
270 - (NSString*)AXRole {
271 if (!node_)
272 return nil;
273 return [[self class] nativeRoleFromAXRole:node_->GetRole()];
274 }
275
276 - (NSValue*)AXSize {
277 return [NSValue valueWithSize:self.boundsInScreen.size];
278 }
279
280 @end
281
282 namespace ui {
283
284 // static
285 AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) {
286 AXPlatformNode* node = new AXPlatformNodeMac();
287 node->Init(delegate);
288 return node;
289 }
290
291 AXPlatformNodeMac::AXPlatformNodeMac() {
292 }
293
294 AXPlatformNodeMac::~AXPlatformNodeMac() {
295 }
296
297 void AXPlatformNodeMac::Detach() {
298 if (native_node_)
299 [native_node_ detach];
300 delegate_ = NULL;
301 delete this;
302 }
303
304 gfx::NativeViewAccessible AXPlatformNodeMac::GetNativeViewAccessible() {
305 if (!native_node_)
306 native_node_.reset([[AXPlatformNodeCocoa alloc] initWithNode:this]);
307 return native_node_.get();
308 }
309
310 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698