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

Side by Side Diff: content/browser/accessibility/browser_accessibility_gtk.cc

Issue 21148002: Implement AtkComponent and AtkValue interfaces. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 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
« no previous file with comments | « content/browser/accessibility/browser_accessibility_gtk.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "content/browser/accessibility/browser_accessibility_gtk.h" 5 #include "content/browser/accessibility/browser_accessibility_gtk.h"
6 6
7 #include <gtk/gtk.h> 7 #include <gtk/gtk.h>
8 8
9 #include "base/strings/utf_string_conversions.h" 9 #include "base/strings/utf_string_conversions.h"
10 #include "content/browser/accessibility/browser_accessibility_manager_gtk.h" 10 #include "content/browser/accessibility/browser_accessibility_manager_gtk.h"
11 #include "content/common/accessibility_messages.h" 11 #include "content/common/accessibility_messages.h"
12 12
13 namespace content { 13 namespace content {
14 14
15 // The maximum length of an autogenerated unique type name string,
16 // generated from the 16-bit interface mask from an AtkObject.
17 // 30 is enough for the prefix "WAIType" + 5 hex chars (max) */
18 static const int kWAITypeNameLen = 30;
19
20 static gpointer browser_accessibility_parent_class = NULL; 15 static gpointer browser_accessibility_parent_class = NULL;
21 16
22 static BrowserAccessibilityGtk* ToBrowserAccessibilityGtk( 17 static BrowserAccessibilityGtk* ToBrowserAccessibilityGtk(
23 BrowserAccessibilityAtk* atk_object) { 18 BrowserAccessibilityAtk* atk_object) {
24 if (!atk_object) 19 if (!atk_object)
25 return NULL; 20 return NULL;
26 21
27 return atk_object->m_object; 22 return atk_object->m_object;
28 } 23 }
29 24
25 //
26 // AtkComponent interface.
27 //
28
29 static BrowserAccessibilityGtk* ToBrowserAccessibilityGtk(
30 AtkComponent* atk_object) {
31 if (!IS_BROWSER_ACCESSIBILITY(atk_object))
32 return NULL;
33
34 return ToBrowserAccessibilityGtk(BROWSER_ACCESSIBILITY(atk_object));
35 }
36
37 static AtkObject* browser_accessibility_accessible_at_point(
38 AtkComponent* component, gint x, gint y, AtkCoordType coord_type) {
39 BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(component);
40 if (!obj)
41 return 0;
aboxhall 2013/07/29 22:23:09 Why return 0 instead of NULL here?
dmazzoni 2013/07/29 22:34:28 Done.
42
43 gfx::Point point(x, y);
44 if (!obj->GetGlobalBoundsRect().Contains(point))
45 return NULL;
46
47 BrowserAccessibility* result = obj->BrowserAccessibilityForPoint(point);
48 if (!result)
49 return NULL;
50
51 AtkObject* atk_result = result->ToBrowserAccessibilityGtk()->GetAtkObject();
52 g_object_ref(atk_result);
53 return atk_result;
54 }
55
56 static void browser_accessibility_get_extents(
57 AtkComponent* component, gint* x, gint* y, gint* width, gint* height,
58 AtkCoordType coord_type) {
59 BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(component);
60 if (!obj)
61 return;
62
63 gfx::Rect bounds = obj->GetGlobalBoundsRect();
aboxhall 2013/07/29 22:23:09 Does bounds need any sanity (null) checking?
dmazzoni 2013/07/29 22:34:28 Not needed, it's just a struct.
64 *x = bounds.x();
65 *y = bounds.y();
66 *width = bounds.width();
67 *height = bounds.height();
68 }
69
70 static gboolean browser_accessibility_grab_focus(AtkComponent* component) {
71 BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(component);
72 if (!obj)
73 return false;
74
75 obj->manager()->SetFocus(obj, true);
76 return true;
77 }
78
79 static void ComponentInterfaceInit(AtkComponentIface* iface) {
80 iface->ref_accessible_at_point = browser_accessibility_accessible_at_point;
81 iface->get_extents = browser_accessibility_get_extents;
82 iface->grab_focus = browser_accessibility_grab_focus;
83 }
84
85 static const GInterfaceInfo ComponentInfo = {
86 reinterpret_cast<GInterfaceInitFunc>(ComponentInterfaceInit), 0, 0
87 };
88
89 //
90 // AtkValue interface.
91 //
92
93 static BrowserAccessibilityGtk* ToBrowserAccessibilityGtk(
94 AtkValue* atk_object) {
95 if (!IS_BROWSER_ACCESSIBILITY(atk_object))
96 return NULL;
97
98 return ToBrowserAccessibilityGtk(BROWSER_ACCESSIBILITY(atk_object));
99 }
100
101 static void browser_accessibility_get_current_value(
102 AtkValue* atk_object, GValue* value) {
103 BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object);
104 if (!obj)
105 return;
106
107 float float_val;
108 if (obj->GetFloatAttribute(AccessibilityNodeData::ATTR_VALUE_FOR_RANGE,
109 &float_val)) {
110 memset(value, 0, sizeof(value));
111 g_value_init(value, G_TYPE_FLOAT);
112 g_value_set_float(value, float_val);
113 }
114 }
115
116 static void browser_accessibility_get_minimum_value(
117 AtkValue* atk_object, GValue* value) {
118 BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object);
119 if (!obj)
120 return;
121
122 float float_val;
123 if (obj->GetFloatAttribute(AccessibilityNodeData::ATTR_MIN_VALUE_FOR_RANGE,
124 &float_val)) {
125 memset(value, 0, sizeof(value));
126 g_value_init(value, G_TYPE_FLOAT);
127 g_value_set_float(value, float_val);
128 }
129 }
130
131 static void browser_accessibility_get_maximum_value(
132 AtkValue* atk_object, GValue* value) {
133 BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object);
134 if (!obj)
135 return;
136
137 float float_val;
138 if (obj->GetFloatAttribute(AccessibilityNodeData::ATTR_MAX_VALUE_FOR_RANGE,
139 &float_val)) {
140 memset(value, 0, sizeof(value));
141 g_value_init(value, G_TYPE_FLOAT);
142 g_value_set_float(value, float_val);
143 }
144 }
145
146 static void browser_accessibility_get_minimum_increment(
147 AtkValue* atk_object, GValue* value) {
148 BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object);
aboxhall 2013/07/29 22:23:09 obj isn't used below; do we still need this check?
dmazzoni 2013/07/29 22:34:28 Done.
149 if (!obj)
150 return;
151
152 memset(value, 0, sizeof(value));
153 g_value_init(value, G_TYPE_FLOAT);
154 g_value_set_float(value, 1.0);
aboxhall 2013/07/29 22:23:09 Is this always correct?
dmazzoni 2013/07/29 22:34:28 No. I added a TODO; I believe the other platforms
155 }
156
157 static void ValueInterfaceInit(AtkValueIface* iface) {
158 iface->get_current_value = browser_accessibility_get_current_value;
159 iface->get_minimum_value = browser_accessibility_get_minimum_value;
160 iface->get_maximum_value = browser_accessibility_get_maximum_value;
161 iface->get_minimum_increment = browser_accessibility_get_minimum_increment;
162 }
163
164 static const GInterfaceInfo ValueInfo = {
165 reinterpret_cast<GInterfaceInitFunc>(ValueInterfaceInit), 0, 0
166 };
167
168 //
169 // AtkObject interface
170 //
171
30 static BrowserAccessibilityGtk* ToBrowserAccessibilityGtk( 172 static BrowserAccessibilityGtk* ToBrowserAccessibilityGtk(
31 AtkObject* atk_object) { 173 AtkObject* atk_object) {
32 if (!IS_BROWSER_ACCESSIBILITY(atk_object)) 174 if (!IS_BROWSER_ACCESSIBILITY(atk_object))
33 return NULL; 175 return NULL;
34 176
35 return ToBrowserAccessibilityGtk(BROWSER_ACCESSIBILITY(atk_object)); 177 return ToBrowserAccessibilityGtk(BROWSER_ACCESSIBILITY(atk_object));
36 } 178 }
37 179
38 static const gchar* browser_accessibility_get_name(AtkObject* atk_object) { 180 static const gchar* browser_accessibility_get_name(AtkObject* atk_object) {
39 BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object); 181 BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object);
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 } 261 }
120 262
121 static AtkRelationSet* browser_accessibility_ref_relation_set( 263 static AtkRelationSet* browser_accessibility_ref_relation_set(
122 AtkObject* atk_object) { 264 AtkObject* atk_object) {
123 AtkRelationSet* relation_set = 265 AtkRelationSet* relation_set =
124 ATK_OBJECT_CLASS(browser_accessibility_parent_class) 266 ATK_OBJECT_CLASS(browser_accessibility_parent_class)
125 ->ref_relation_set(atk_object); 267 ->ref_relation_set(atk_object);
126 return relation_set; 268 return relation_set;
127 } 269 }
128 270
271 //
272 // The rest of the BrowserAccessibilityGtk code, not specific to one
273 // of the Atk* interfaces.
274 //
275
129 static void browser_accessibility_init(AtkObject* atk_object, gpointer data) { 276 static void browser_accessibility_init(AtkObject* atk_object, gpointer data) {
130 if (ATK_OBJECT_CLASS(browser_accessibility_parent_class)->initialize) { 277 if (ATK_OBJECT_CLASS(browser_accessibility_parent_class)->initialize) {
131 ATK_OBJECT_CLASS(browser_accessibility_parent_class)->initialize( 278 ATK_OBJECT_CLASS(browser_accessibility_parent_class)->initialize(
132 atk_object, data); 279 atk_object, data);
133 } 280 }
134 281
135 BROWSER_ACCESSIBILITY(atk_object)->m_object = 282 BROWSER_ACCESSIBILITY(atk_object)->m_object =
136 reinterpret_cast<BrowserAccessibilityGtk*>(data); 283 reinterpret_cast<BrowserAccessibilityGtk*>(data);
137 } 284 }
138 285
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 }; 323 };
177 324
178 GType type = g_type_register_static( 325 GType type = g_type_register_static(
179 ATK_TYPE_OBJECT, "BrowserAccessibility", &tinfo, GTypeFlags(0)); 326 ATK_TYPE_OBJECT, "BrowserAccessibility", &tinfo, GTypeFlags(0));
180 g_once_init_leave(&type_volatile, type); 327 g_once_init_leave(&type_volatile, type);
181 } 328 }
182 329
183 return type_volatile; 330 return type_volatile;
184 } 331 }
185 332
186 static guint16 GetInterfaceMaskFromObject(BrowserAccessibilityGtk* obj) { 333 static const char* GetUniqueAccessibilityTypeName(int interface_mask)
187 return 0;
188 }
189
190 static const char* GetUniqueAccessibilityTypeName(guint16 interface_mask)
191 { 334 {
192 static char name[kWAITypeNameLen + 1]; 335 // 20 characters is enough for "Chrome%x" with any conceivable integer.
aboxhall 2013/07/29 22:23:09 What does 'conceivable' mean here?
dmazzoni 2013/07/29 22:34:28 Done.
193 336 static char name[20];
194 sprintf(name, "WAIType%x", interface_mask); 337 snprintf(name, sizeof(name), "Chrome%x", interface_mask);
195 name[kWAITypeNameLen] = '\0';
196
197 return name; 338 return name;
198 } 339 }
199 340
200 static const GInterfaceInfo AtkInterfacesInitFunctions[] = { 341 enum AtkInterfaces {
342 ATK_ACTION_INTERFACE,
343 ATK_COMPONENT_INTERFACE,
344 ATK_DOCUMENT_INTERFACE,
345 ATK_EDITABLE_TEXT_INTERFACE,
346 ATK_HYPERLINK_INTERFACE,
347 ATK_HYPERTEXT_INTERFACE,
348 ATK_IMAGE_INTERFACE,
349 ATK_SELECTION_INTERFACE,
350 ATK_TABLE_INTERFACE,
351 ATK_TEXT_INTERFACE,
352 ATK_VALUE_INTERFACE,
201 }; 353 };
202 354
203 enum WAIType { 355 static int GetInterfaceMaskFromObject(BrowserAccessibilityGtk* obj) {
204 WAI_ACTION, 356 int interface_mask = 0;
205 WAI_SELECTION,
206 WAI_EDITABLE_TEXT,
207 WAI_TEXT,
208 WAI_COMPONENT,
209 WAI_IMAGE,
210 WAI_TABLE,
211 WAI_HYPERTEXT,
212 WAI_HYPERLINK,
213 WAI_DOCUMENT,
214 WAI_VALUE,
215 };
216 357
217 static GType GetAtkInterfaceTypeFromWAIType(WAIType type) { 358 // Component interface is always supported.
218 switch (type) { 359 interface_mask |= 1 << ATK_COMPONENT_INTERFACE;
219 case WAI_ACTION: 360
220 return ATK_TYPE_ACTION; 361 int role = obj->role();
221 case WAI_SELECTION: 362 if (role == AccessibilityNodeData::ROLE_PROGRESS_INDICATOR ||
aboxhall 2013/07/29 22:23:09 So we'll need to go through each of the roles and
dmazzoni 2013/07/29 22:34:28 Yes. Usually it's pretty easy; for example the TAB
222 return ATK_TYPE_SELECTION; 363 role == AccessibilityNodeData::ROLE_SCROLLBAR ||
223 case WAI_EDITABLE_TEXT: 364 role == AccessibilityNodeData::ROLE_SLIDER) {
224 return ATK_TYPE_EDITABLE_TEXT; 365 interface_mask |= 1 << ATK_VALUE_INTERFACE;
225 case WAI_TEXT:
226 return ATK_TYPE_TEXT;
227 case WAI_COMPONENT:
228 return ATK_TYPE_COMPONENT;
229 case WAI_IMAGE:
230 return ATK_TYPE_IMAGE;
231 case WAI_TABLE:
232 return ATK_TYPE_TABLE;
233 case WAI_HYPERTEXT:
234 return ATK_TYPE_HYPERTEXT;
235 case WAI_HYPERLINK:
236 return ATK_TYPE_HYPERLINK_IMPL;
237 case WAI_DOCUMENT:
238 return ATK_TYPE_DOCUMENT;
239 case WAI_VALUE:
240 return ATK_TYPE_VALUE;
241 } 366 }
242 367
243 return G_TYPE_INVALID; 368 return interface_mask;
244 } 369 }
245 370
246 static GType GetAccessibilityTypeFromObject(BrowserAccessibilityGtk* obj) { 371 static GType GetAccessibilityTypeFromObject(BrowserAccessibilityGtk* obj) {
247 static const GTypeInfo type_info = { 372 static const GTypeInfo type_info = {
248 sizeof(BrowserAccessibilityAtkClass), 373 sizeof(BrowserAccessibilityAtkClass),
249 (GBaseInitFunc) 0, 374 (GBaseInitFunc) 0,
250 (GBaseFinalizeFunc) 0, 375 (GBaseFinalizeFunc) 0,
251 (GClassInitFunc) 0, 376 (GClassInitFunc) 0,
252 (GClassFinalizeFunc) 0, 377 (GClassFinalizeFunc) 0,
253 0, /* class data */ 378 0, /* class data */
254 sizeof(BrowserAccessibilityAtk), /* instance size */ 379 sizeof(BrowserAccessibilityAtk), /* instance size */
255 0, /* nb preallocs */ 380 0, /* nb preallocs */
256 (GInstanceInitFunc) 0, 381 (GInstanceInitFunc) 0,
257 0 /* value table */ 382 0 /* value table */
258 }; 383 };
259 384
260 guint16 interface_mask = GetInterfaceMaskFromObject(obj); 385 int interface_mask = GetInterfaceMaskFromObject(obj);
261 const char* atk_type_name = GetUniqueAccessibilityTypeName(interface_mask); 386 const char* atk_type_name = GetUniqueAccessibilityTypeName(interface_mask);
262 GType type = g_type_from_name(atk_type_name); 387 GType type = g_type_from_name(atk_type_name);
263 if (type) 388 if (type)
264 return type; 389 return type;
265 390
266 type = g_type_register_static(BROWSER_ACCESSIBILITY_TYPE, 391 type = g_type_register_static(BROWSER_ACCESSIBILITY_TYPE,
267 atk_type_name, 392 atk_type_name,
268 &type_info, 393 &type_info,
269 GTypeFlags(0)); 394 GTypeFlags(0));
270 for (guint i = 0; i < G_N_ELEMENTS(AtkInterfacesInitFunctions); i++) { 395 if (interface_mask & (1 << ATK_COMPONENT_INTERFACE))
271 if (interface_mask & (1 << i)) { 396 g_type_add_interface_static(type, ATK_TYPE_COMPONENT, &ComponentInfo);
272 g_type_add_interface_static( 397 if (interface_mask & (1 << ATK_VALUE_INTERFACE))
273 type, 398 g_type_add_interface_static(type, ATK_TYPE_VALUE, &ValueInfo);
274 GetAtkInterfaceTypeFromWAIType(static_cast<WAIType>(i)),
275 &AtkInterfacesInitFunctions[i]);
276 }
277 }
278 399
279 return type; 400 return type;
280 } 401 }
281 402
282 BrowserAccessibilityAtk* browser_accessibility_new( 403 BrowserAccessibilityAtk* browser_accessibility_new(
283 BrowserAccessibilityGtk* obj) { 404 BrowserAccessibilityGtk* obj) {
284 GType type = GetAccessibilityTypeFromObject(obj); 405 GType type = GetAccessibilityTypeFromObject(obj);
285 AtkObject* atk_object = static_cast<AtkObject*>(g_object_new(type, 0)); 406 AtkObject* atk_object = static_cast<AtkObject*>(g_object_new(type, 0));
286 407
287 atk_object_initialize(atk_object, obj); 408 atk_object_initialize(atk_object, obj);
288 409
289 return BROWSER_ACCESSIBILITY(atk_object); 410 return BROWSER_ACCESSIBILITY(atk_object);
290 } 411 }
291 412
292 void browser_accessibility_detach(BrowserAccessibilityAtk* atk_object) { 413 void browser_accessibility_detach(BrowserAccessibilityAtk* atk_object) {
293 atk_object->m_object = NULL; 414 atk_object->m_object = NULL;
294 } 415 }
295 416
296 // static 417 // static
297 BrowserAccessibility* BrowserAccessibility::Create() { 418 BrowserAccessibility* BrowserAccessibility::Create() {
298 return new BrowserAccessibilityGtk(); 419 return new BrowserAccessibilityGtk();
299 } 420 }
300 421
301 BrowserAccessibilityGtk* BrowserAccessibility::ToBrowserAccessibilityGtk() { 422 BrowserAccessibilityGtk* BrowserAccessibility::ToBrowserAccessibilityGtk() {
302 return static_cast<BrowserAccessibilityGtk*>(this); 423 return static_cast<BrowserAccessibilityGtk*>(this);
303 } 424 }
304 425
305 BrowserAccessibilityGtk::BrowserAccessibilityGtk() { 426 BrowserAccessibilityGtk::BrowserAccessibilityGtk()
306 atk_object_ = ATK_OBJECT(browser_accessibility_new(this)); 427 : atk_object_(NULL) {
307 } 428 }
308 429
309 BrowserAccessibilityGtk::~BrowserAccessibilityGtk() { 430 BrowserAccessibilityGtk::~BrowserAccessibilityGtk() {
310 browser_accessibility_detach(BROWSER_ACCESSIBILITY(atk_object_)); 431 browser_accessibility_detach(BROWSER_ACCESSIBILITY(atk_object_));
311 g_object_unref(atk_object_); 432 if (atk_object_)
433 g_object_unref(atk_object_);
312 } 434 }
313 435
314 AtkObject* BrowserAccessibilityGtk::GetAtkObject() const { 436 AtkObject* BrowserAccessibilityGtk::GetAtkObject() const {
315 if (!G_IS_OBJECT(atk_object_)) 437 if (!G_IS_OBJECT(atk_object_))
316 return NULL; 438 return NULL;
317 return atk_object_; 439 return atk_object_;
318 } 440 }
319 441
320 void BrowserAccessibilityGtk::PreInitialize() { 442 void BrowserAccessibilityGtk::PreInitialize() {
321 BrowserAccessibility::PreInitialize(); 443 BrowserAccessibility::PreInitialize();
322 InitRoleAndState(); 444 InitRoleAndState();
323 445
324 if (this->parent()) { 446 if (atk_object_) {
325 atk_object_set_parent( 447 // If the object's role changes and that causes its
326 atk_object_, 448 // interface mask to change, we need to create a new
327 this->parent()->ToBrowserAccessibilityGtk()->GetAtkObject()); 449 // AtkObject for it.
450 int interface_mask = GetInterfaceMaskFromObject(this);
451 if (interface_mask != interface_mask_) {
452 g_object_unref(atk_object_);
453 atk_object_ = NULL;
454 }
455 }
456
457 if (!atk_object_) {
458 interface_mask_ = GetInterfaceMaskFromObject(this);
459 atk_object_ = ATK_OBJECT(browser_accessibility_new(this));
460 if (this->parent()) {
461 atk_object_set_parent(
462 atk_object_,
463 this->parent()->ToBrowserAccessibilityGtk()->GetAtkObject());
464 }
328 } 465 }
329 } 466 }
330 467
331 bool BrowserAccessibilityGtk::IsNative() const { 468 bool BrowserAccessibilityGtk::IsNative() const {
332 return true; 469 return true;
333 } 470 }
334 471
335 void BrowserAccessibilityGtk::InitRoleAndState() { 472 void BrowserAccessibilityGtk::InitRoleAndState() {
336 atk_acc_name_ = UTF16ToUTF8(name()); 473 atk_acc_name_ = UTF16ToUTF8(name());
337 474
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 case AccessibilityNodeData::ROLE_WEBCORE_LINK: 513 case AccessibilityNodeData::ROLE_WEBCORE_LINK:
377 atk_role_ = ATK_ROLE_LINK; 514 atk_role_ = ATK_ROLE_LINK;
378 break; 515 break;
379 default: 516 default:
380 atk_role_ = ATK_ROLE_UNKNOWN; 517 atk_role_ = ATK_ROLE_UNKNOWN;
381 break; 518 break;
382 } 519 }
383 } 520 }
384 521
385 } // namespace content 522 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/accessibility/browser_accessibility_gtk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698