1 // Copyright (c) 2015 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.
5 #include "content/browser/accessibility/browser_accessibility_auralinux.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "content/browser/accessibility/browser_accessibility_manager_auralinux.h"
9 #include "content/common/accessibility_messages.h"
13 static gpointer browser_accessibility_parent_class
= NULL
;
15 static BrowserAccessibilityAuraLinux
* ToBrowserAccessibilityAuraLinux(
16 BrowserAccessibilityAtk
* atk_object
) {
20 return atk_object
->m_object
;
24 // AtkComponent interface.
27 static BrowserAccessibilityAuraLinux
* ToBrowserAccessibilityAuraLinux(
28 AtkComponent
* atk_component
) {
29 if (!IS_BROWSER_ACCESSIBILITY(atk_component
))
32 return ToBrowserAccessibilityAuraLinux(BROWSER_ACCESSIBILITY(atk_component
));
35 static AtkObject
* browser_accessibility_accessible_at_point(
36 AtkComponent
* atk_component
,
39 AtkCoordType coord_type
) {
40 g_return_val_if_fail(ATK_IS_COMPONENT(atk_component
), 0);
42 BrowserAccessibilityAuraLinux
* obj
=
43 ToBrowserAccessibilityAuraLinux(atk_component
);
47 gfx::Point
point(x
, y
);
48 if (!obj
->GetGlobalBoundsRect().Contains(point
))
51 BrowserAccessibility
* result
= obj
->BrowserAccessibilityForPoint(point
);
55 AtkObject
* atk_result
=
56 result
->ToBrowserAccessibilityAuraLinux()->GetAtkObject();
57 g_object_ref(atk_result
);
61 static void browser_accessibility_get_extents(AtkComponent
* atk_component
,
66 AtkCoordType coord_type
) {
67 g_return_if_fail(ATK_IS_COMPONENT(atk_component
));
69 BrowserAccessibilityAuraLinux
* obj
=
70 ToBrowserAccessibilityAuraLinux(atk_component
);
74 gfx::Rect bounds
= obj
->GetGlobalBoundsRect();
80 *width
= bounds
.width();
82 *height
= bounds
.height();
85 static gboolean
browser_accessibility_grab_focus(AtkComponent
* atk_component
) {
86 g_return_val_if_fail(ATK_IS_COMPONENT(atk_component
), FALSE
);
88 BrowserAccessibilityAuraLinux
* obj
=
89 ToBrowserAccessibilityAuraLinux(atk_component
);
93 obj
->manager()->SetFocus(obj
, true);
97 static void ComponentInterfaceInit(AtkComponentIface
* iface
) {
98 iface
->ref_accessible_at_point
= browser_accessibility_accessible_at_point
;
99 iface
->get_extents
= browser_accessibility_get_extents
;
100 iface
->grab_focus
= browser_accessibility_grab_focus
;
103 static const GInterfaceInfo ComponentInfo
= {
104 reinterpret_cast<GInterfaceInitFunc
>(ComponentInterfaceInit
),
109 // AtkValue interface.
112 static BrowserAccessibilityAuraLinux
* ToBrowserAccessibilityAuraLinux(
113 AtkValue
* atk_object
) {
114 if (!IS_BROWSER_ACCESSIBILITY(atk_object
))
117 return ToBrowserAccessibilityAuraLinux(BROWSER_ACCESSIBILITY(atk_object
));
120 static float GetStepAttribute(BrowserAccessibilityAuraLinux
* obj
) {
121 // TODO(shreeram.k): Get Correct value of Step attribute.
125 static void browser_accessibility_get_current_value(AtkValue
* atk_value
,
127 g_return_if_fail(ATK_VALUE(atk_value
));
129 BrowserAccessibilityAuraLinux
* obj
=
130 ToBrowserAccessibilityAuraLinux(atk_value
);
135 if (obj
->GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE
, &float_val
)) {
136 memset(value
, 0, sizeof(*value
));
137 g_value_init(value
, G_TYPE_FLOAT
);
138 g_value_set_float(value
, float_val
);
142 static void browser_accessibility_get_minimum_value(AtkValue
* atk_value
,
144 g_return_if_fail(ATK_VALUE(atk_value
));
146 BrowserAccessibilityAuraLinux
* obj
=
147 ToBrowserAccessibilityAuraLinux(atk_value
);
152 if (obj
->GetFloatAttribute(ui::AX_ATTR_MIN_VALUE_FOR_RANGE
, &float_val
)) {
153 memset(value
, 0, sizeof(*value
));
154 g_value_init(value
, G_TYPE_FLOAT
);
155 g_value_set_float(value
, float_val
);
159 static void browser_accessibility_get_maximum_value(AtkValue
* atk_value
,
161 g_return_if_fail(ATK_VALUE(atk_value
));
163 BrowserAccessibilityAuraLinux
* obj
=
164 ToBrowserAccessibilityAuraLinux(atk_value
);
169 if (obj
->GetFloatAttribute(ui::AX_ATTR_MAX_VALUE_FOR_RANGE
, &float_val
)) {
170 memset(value
, 0, sizeof(*value
));
171 g_value_init(value
, G_TYPE_FLOAT
);
172 g_value_set_float(value
, float_val
);
176 static void browser_accessibility_get_minimum_increment(AtkValue
* atk_value
,
178 g_return_if_fail(ATK_VALUE(atk_value
));
180 memset(gValue
, 0, sizeof(GValue
));
181 g_value_init(gValue
, G_TYPE_FLOAT
);
183 BrowserAccessibilityAuraLinux
* obj
=
184 ToBrowserAccessibilityAuraLinux(atk_value
);
188 g_value_set_float(gValue
, GetStepAttribute(obj
));
191 static void ValueInterfaceInit(AtkValueIface
* iface
) {
192 iface
->get_current_value
= browser_accessibility_get_current_value
;
193 iface
->get_minimum_value
= browser_accessibility_get_minimum_value
;
194 iface
->get_maximum_value
= browser_accessibility_get_maximum_value
;
195 iface
->get_minimum_increment
= browser_accessibility_get_minimum_increment
;
198 static const GInterfaceInfo ValueInfo
= {
199 reinterpret_cast<GInterfaceInitFunc
>(ValueInterfaceInit
),
204 // AtkObject interface
207 static BrowserAccessibilityAuraLinux
* ToBrowserAccessibilityAuraLinux(
208 AtkObject
* atk_object
) {
209 if (!IS_BROWSER_ACCESSIBILITY(atk_object
))
212 return ToBrowserAccessibilityAuraLinux(BROWSER_ACCESSIBILITY(atk_object
));
215 static const gchar
* browser_accessibility_get_name(AtkObject
* atk_object
) {
216 BrowserAccessibilityAuraLinux
* obj
=
217 ToBrowserAccessibilityAuraLinux(atk_object
);
221 return obj
->GetStringAttribute(ui::AX_ATTR_NAME
).c_str();
224 static const gchar
* browser_accessibility_get_description(
225 AtkObject
* atk_object
) {
226 BrowserAccessibilityAuraLinux
* obj
=
227 ToBrowserAccessibilityAuraLinux(atk_object
);
231 return obj
->GetStringAttribute(ui::AX_ATTR_DESCRIPTION
).c_str();
234 static AtkObject
* browser_accessibility_get_parent(AtkObject
* atk_object
) {
235 BrowserAccessibilityAuraLinux
* obj
=
236 ToBrowserAccessibilityAuraLinux(atk_object
);
239 if (obj
->GetParent())
240 return obj
->GetParent()->ToBrowserAccessibilityAuraLinux()->GetAtkObject();
242 BrowserAccessibilityManagerAuraLinux
* manager
=
243 static_cast<BrowserAccessibilityManagerAuraLinux
*>(obj
->manager());
244 return manager
->parent_object();
247 static gint
browser_accessibility_get_n_children(AtkObject
* atk_object
) {
248 BrowserAccessibilityAuraLinux
* obj
=
249 ToBrowserAccessibilityAuraLinux(atk_object
);
253 return obj
->PlatformChildCount();
256 static AtkObject
* browser_accessibility_ref_child(AtkObject
* atk_object
,
258 BrowserAccessibilityAuraLinux
* obj
=
259 ToBrowserAccessibilityAuraLinux(atk_object
);
263 if (index
< 0 || index
>= static_cast<gint
>(obj
->PlatformChildCount()))
266 AtkObject
* result
= obj
->InternalGetChild(index
)
267 ->ToBrowserAccessibilityAuraLinux()
269 g_object_ref(result
);
273 static gint
browser_accessibility_get_index_in_parent(AtkObject
* atk_object
) {
274 BrowserAccessibilityAuraLinux
* obj
=
275 ToBrowserAccessibilityAuraLinux(atk_object
);
278 return obj
->GetIndexInParent();
281 static AtkAttributeSet
* browser_accessibility_get_attributes(
282 AtkObject
* atk_object
) {
286 static AtkRole
browser_accessibility_get_role(AtkObject
* atk_object
) {
287 BrowserAccessibilityAuraLinux
* obj
=
288 ToBrowserAccessibilityAuraLinux(atk_object
);
290 return ATK_ROLE_INVALID
;
291 return obj
->atk_role();
294 static AtkStateSet
* browser_accessibility_ref_state_set(AtkObject
* atk_object
) {
295 BrowserAccessibilityAuraLinux
* obj
=
296 ToBrowserAccessibilityAuraLinux(atk_object
);
299 AtkStateSet
* state_set
= ATK_OBJECT_CLASS(browser_accessibility_parent_class
)
300 ->ref_state_set(atk_object
);
301 int32 state
= obj
->GetState();
303 if (state
& (1 << ui::AX_STATE_FOCUSABLE
))
304 atk_state_set_add_state(state_set
, ATK_STATE_FOCUSABLE
);
305 if (obj
->manager()->GetFocus(NULL
) == obj
)
306 atk_state_set_add_state(state_set
, ATK_STATE_FOCUSED
);
307 if (state
& (1 << ui::AX_STATE_ENABLED
))
308 atk_state_set_add_state(state_set
, ATK_STATE_ENABLED
);
313 static AtkRelationSet
* browser_accessibility_ref_relation_set(
314 AtkObject
* atk_object
) {
315 AtkRelationSet
* relation_set
=
316 ATK_OBJECT_CLASS(browser_accessibility_parent_class
)
317 ->ref_relation_set(atk_object
);
322 // The rest of the BrowserAccessibilityAuraLinux code, not specific to one
323 // of the Atk* interfaces.
326 static void browser_accessibility_init(AtkObject
* atk_object
, gpointer data
) {
327 if (ATK_OBJECT_CLASS(browser_accessibility_parent_class
)->initialize
) {
328 ATK_OBJECT_CLASS(browser_accessibility_parent_class
)
329 ->initialize(atk_object
, data
);
332 BROWSER_ACCESSIBILITY(atk_object
)->m_object
=
333 reinterpret_cast<BrowserAccessibilityAuraLinux
*>(data
);
336 static void browser_accessibility_finalize(GObject
* atk_object
) {
337 G_OBJECT_CLASS(browser_accessibility_parent_class
)->finalize(atk_object
);
340 static void browser_accessibility_class_init(AtkObjectClass
* klass
) {
341 GObjectClass
* gobject_class
= G_OBJECT_CLASS(klass
);
342 browser_accessibility_parent_class
= g_type_class_peek_parent(klass
);
344 gobject_class
->finalize
= browser_accessibility_finalize
;
345 klass
->initialize
= browser_accessibility_init
;
346 klass
->get_name
= browser_accessibility_get_name
;
347 klass
->get_description
= browser_accessibility_get_description
;
348 klass
->get_parent
= browser_accessibility_get_parent
;
349 klass
->get_n_children
= browser_accessibility_get_n_children
;
350 klass
->ref_child
= browser_accessibility_ref_child
;
351 klass
->get_role
= browser_accessibility_get_role
;
352 klass
->ref_state_set
= browser_accessibility_ref_state_set
;
353 klass
->get_index_in_parent
= browser_accessibility_get_index_in_parent
;
354 klass
->get_attributes
= browser_accessibility_get_attributes
;
355 klass
->ref_relation_set
= browser_accessibility_ref_relation_set
;
358 GType
browser_accessibility_get_type() {
359 static volatile gsize type_volatile
= 0;
361 #if !GLIB_CHECK_VERSION(2, 36, 0)
365 if (g_once_init_enter(&type_volatile
)) {
366 static const GTypeInfo tinfo
= {
367 sizeof(BrowserAccessibilityAtkClass
),
369 (GBaseFinalizeFunc
)0,
370 (GClassInitFunc
)browser_accessibility_class_init
,
371 (GClassFinalizeFunc
)0,
373 sizeof(BrowserAccessibilityAtk
), /* instance size */
374 0, /* nb preallocs */
375 (GInstanceInitFunc
)0,
379 GType type
= g_type_register_static(ATK_TYPE_OBJECT
, "BrowserAccessibility",
380 &tinfo
, GTypeFlags(0));
381 g_once_init_leave(&type_volatile
, type
);
384 return type_volatile
;
387 static const char* GetUniqueAccessibilityTypeName(int interface_mask
) {
388 // 20 characters is enough for "Chrome%x" with any integer value.
389 static char name
[20];
390 snprintf(name
, sizeof(name
), "Chrome%x", interface_mask
);
395 ATK_ACTION_INTERFACE
,
396 ATK_COMPONENT_INTERFACE
,
397 ATK_DOCUMENT_INTERFACE
,
398 ATK_EDITABLE_TEXT_INTERFACE
,
399 ATK_HYPERLINK_INTERFACE
,
400 ATK_HYPERTEXT_INTERFACE
,
402 ATK_SELECTION_INTERFACE
,
408 static int GetInterfaceMaskFromObject(BrowserAccessibilityAuraLinux
* obj
) {
409 int interface_mask
= 0;
411 // Component interface is always supported.
412 interface_mask
|= 1 << ATK_COMPONENT_INTERFACE
;
414 int role
= obj
->GetRole();
415 if (role
== ui::AX_ROLE_PROGRESS_INDICATOR
||
416 role
== ui::AX_ROLE_SCROLL_BAR
|| role
== ui::AX_ROLE_SLIDER
) {
417 interface_mask
|= 1 << ATK_VALUE_INTERFACE
;
420 return interface_mask
;
423 static GType
GetAccessibilityTypeFromObject(
424 BrowserAccessibilityAuraLinux
* obj
) {
425 static const GTypeInfo type_info
= {
426 sizeof(BrowserAccessibilityAtkClass
),
428 (GBaseFinalizeFunc
)0,
430 (GClassFinalizeFunc
)0,
432 sizeof(BrowserAccessibilityAtk
), /* instance size */
433 0, /* nb preallocs */
434 (GInstanceInitFunc
)0,
438 int interface_mask
= GetInterfaceMaskFromObject(obj
);
439 const char* atk_type_name
= GetUniqueAccessibilityTypeName(interface_mask
);
440 GType type
= g_type_from_name(atk_type_name
);
444 type
= g_type_register_static(BROWSER_ACCESSIBILITY_TYPE
, atk_type_name
,
445 &type_info
, GTypeFlags(0));
446 if (interface_mask
& (1 << ATK_COMPONENT_INTERFACE
))
447 g_type_add_interface_static(type
, ATK_TYPE_COMPONENT
, &ComponentInfo
);
448 if (interface_mask
& (1 << ATK_VALUE_INTERFACE
))
449 g_type_add_interface_static(type
, ATK_TYPE_VALUE
, &ValueInfo
);
454 BrowserAccessibilityAtk
* browser_accessibility_new(
455 BrowserAccessibilityAuraLinux
* obj
) {
456 GType type
= GetAccessibilityTypeFromObject(obj
);
457 AtkObject
* atk_object
= static_cast<AtkObject
*>(g_object_new(type
, 0));
459 atk_object_initialize(atk_object
, obj
);
461 return BROWSER_ACCESSIBILITY(atk_object
);
464 void browser_accessibility_detach(BrowserAccessibilityAtk
* atk_object
) {
465 atk_object
->m_object
= NULL
;
469 BrowserAccessibility
* BrowserAccessibility::Create() {
470 return new BrowserAccessibilityAuraLinux();
473 BrowserAccessibilityAuraLinux
*
474 BrowserAccessibility::ToBrowserAccessibilityAuraLinux() {
475 return static_cast<BrowserAccessibilityAuraLinux
*>(this);
478 BrowserAccessibilityAuraLinux::BrowserAccessibilityAuraLinux()
479 : atk_object_(NULL
) {
482 BrowserAccessibilityAuraLinux::~BrowserAccessibilityAuraLinux() {
483 browser_accessibility_detach(BROWSER_ACCESSIBILITY(atk_object_
));
485 g_object_unref(atk_object_
);
488 AtkObject
* BrowserAccessibilityAuraLinux::GetAtkObject() const {
489 if (!G_IS_OBJECT(atk_object_
))
494 void BrowserAccessibilityAuraLinux::OnDataChanged() {
495 BrowserAccessibility::OnDataChanged();
499 // If the object's role changes and that causes its
500 // interface mask to change, we need to create a new
502 int interface_mask
= GetInterfaceMaskFromObject(this);
503 if (interface_mask
!= interface_mask_
) {
504 g_object_unref(atk_object_
);
510 interface_mask_
= GetInterfaceMaskFromObject(this);
511 atk_object_
= ATK_OBJECT(browser_accessibility_new(this));
512 if (this->GetParent()) {
513 atk_object_set_parent(
515 this->GetParent()->ToBrowserAccessibilityAuraLinux()->GetAtkObject());
520 bool BrowserAccessibilityAuraLinux::IsNative() const {
524 void BrowserAccessibilityAuraLinux::InitRoleAndState() {
526 case ui::AX_ROLE_DOCUMENT
:
527 case ui::AX_ROLE_ROOT_WEB_AREA
:
528 case ui::AX_ROLE_WEB_AREA
:
529 atk_role_
= ATK_ROLE_DOCUMENT_WEB
;
531 case ui::AX_ROLE_ALERT
:
532 case ui::AX_ROLE_ALERT_DIALOG
:
533 atk_role_
= ATK_ROLE_ALERT
;
535 case ui::AX_ROLE_APPLICATION
:
536 atk_role_
= ATK_ROLE_APPLICATION
;
538 case ui::AX_ROLE_BUTTON
:
539 atk_role_
= ATK_ROLE_PUSH_BUTTON
;
541 case ui::AX_ROLE_CANVAS
:
542 atk_role_
= ATK_ROLE_CANVAS
;
544 case ui::AX_ROLE_CAPTION
:
545 atk_role_
= ATK_ROLE_CAPTION
;
547 case ui::AX_ROLE_CHECK_BOX
:
548 atk_role_
= ATK_ROLE_CHECK_BOX
;
550 case ui::AX_ROLE_COLOR_WELL
:
551 atk_role_
= ATK_ROLE_COLOR_CHOOSER
;
553 case ui::AX_ROLE_COLUMN_HEADER
:
554 atk_role_
= ATK_ROLE_COLUMN_HEADER
;
556 case ui::AX_ROLE_COMBO_BOX
:
557 atk_role_
= ATK_ROLE_COMBO_BOX
;
559 case ui::AX_ROLE_DATE
:
560 case ui::AX_ROLE_DATE_TIME
:
561 atk_role_
= ATK_ROLE_DATE_EDITOR
;
563 case ui::AX_ROLE_DIALOG
:
564 atk_role_
= ATK_ROLE_DIALOG
;
566 case ui::AX_ROLE_DIV
:
567 case ui::AX_ROLE_GROUP
:
568 atk_role_
= ATK_ROLE_SECTION
;
570 case ui::AX_ROLE_FORM
:
571 atk_role_
= ATK_ROLE_FORM
;
573 case ui::AX_ROLE_IMAGE
:
574 atk_role_
= ATK_ROLE_IMAGE
;
576 case ui::AX_ROLE_IMAGE_MAP
:
577 atk_role_
= ATK_ROLE_IMAGE_MAP
;
579 case ui::AX_ROLE_LABEL_TEXT
:
580 atk_role_
= ATK_ROLE_LABEL
;
582 case ui::AX_ROLE_LINK
:
583 atk_role_
= ATK_ROLE_LINK
;
585 case ui::AX_ROLE_LIST
:
586 atk_role_
= ATK_ROLE_LIST
;
588 case ui::AX_ROLE_LIST_BOX
:
589 atk_role_
= ATK_ROLE_LIST_BOX
;
591 case ui::AX_ROLE_LIST_ITEM
:
592 atk_role_
= ATK_ROLE_LIST_ITEM
;
594 case ui::AX_ROLE_MENU
:
595 atk_role_
= ATK_ROLE_MENU
;
597 case ui::AX_ROLE_MENU_BAR
:
598 atk_role_
= ATK_ROLE_MENU_BAR
;
600 case ui::AX_ROLE_MENU_ITEM
:
601 atk_role_
= ATK_ROLE_MENU_ITEM
;
603 case ui::AX_ROLE_MENU_ITEM_CHECK_BOX
:
604 atk_role_
= ATK_ROLE_CHECK_MENU_ITEM
;
606 case ui::AX_ROLE_MENU_ITEM_RADIO
:
607 atk_role_
= ATK_ROLE_RADIO_MENU_ITEM
;
609 case ui::AX_ROLE_METER
:
610 atk_role_
= ATK_ROLE_PROGRESS_BAR
;
612 case ui::AX_ROLE_PARAGRAPH
:
613 atk_role_
= ATK_ROLE_PARAGRAPH
;
615 case ui::AX_ROLE_RADIO_BUTTON
:
616 atk_role_
= ATK_ROLE_RADIO_BUTTON
;
618 case ui::AX_ROLE_ROW_HEADER
:
619 atk_role_
= ATK_ROLE_ROW_HEADER
;
621 case ui::AX_ROLE_SCROLL_BAR
:
622 atk_role_
= ATK_ROLE_SCROLL_BAR
;
624 case ui::AX_ROLE_SLIDER
:
625 atk_role_
= ATK_ROLE_SLIDER
;
627 case ui::AX_ROLE_SPIN_BUTTON
:
628 atk_role_
= ATK_ROLE_SPIN_BUTTON
;
630 case ui::AX_ROLE_SPLITTER
:
631 atk_role_
= ATK_ROLE_SEPARATOR
;
633 case ui::AX_ROLE_STATIC_TEXT
:
634 atk_role_
= ATK_ROLE_TEXT
;
636 case ui::AX_ROLE_STATUS
:
637 atk_role_
= ATK_ROLE_STATUSBAR
;
639 case ui::AX_ROLE_TAB
:
640 atk_role_
= ATK_ROLE_PAGE_TAB
;
642 case ui::AX_ROLE_TABLE
:
643 atk_role_
= ATK_ROLE_TABLE
;
645 case ui::AX_ROLE_TAB_LIST
:
646 atk_role_
= ATK_ROLE_PAGE_TAB_LIST
;
648 case ui::AX_ROLE_TOGGLE_BUTTON
:
649 atk_role_
= ATK_ROLE_TOGGLE_BUTTON
;
651 case ui::AX_ROLE_TOOLBAR
:
652 atk_role_
= ATK_ROLE_TOOL_BAR
;
654 case ui::AX_ROLE_TOOLTIP
:
655 atk_role_
= ATK_ROLE_TOOL_TIP
;
657 case ui::AX_ROLE_TEXT_FIELD
:
658 atk_role_
= ATK_ROLE_ENTRY
;
660 case ui::AX_ROLE_TREE
:
661 atk_role_
= ATK_ROLE_TREE
;
663 case ui::AX_ROLE_TREE_ITEM
:
664 atk_role_
= ATK_ROLE_TREE_ITEM
;
667 atk_role_
= ATK_ROLE_UNKNOWN
;
672 } // namespace content