1 // Copyright 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 "ui/accessibility/platform/ax_platform_node_auralinux.h"
7 #include "base/command_line.h"
8 #include "base/strings/sys_string_conversions.h"
9 #include "base/task_runner.h"
10 #include "ui/accessibility/ax_node_data.h"
11 #include "ui/accessibility/platform/atk_util_auralinux.h"
12 #include "ui/accessibility/platform/ax_platform_node_delegate.h"
15 // ax_platform_node_auralinux AtkObject definition and implementation.
20 #define AX_PLATFORM_NODE_AURALINUX_TYPE (ax_platform_node_auralinux_get_type())
21 #define AX_PLATFORM_NODE_AURALINUX(obj) \
22 (G_TYPE_CHECK_INSTANCE_CAST( \
23 (obj), AX_PLATFORM_NODE_AURALINUX_TYPE, AXPlatformNodeAuraLinuxObject))
24 #define AX_PLATFORM_NODE_AURALINUX_CLASS(klass) \
25 (G_TYPE_CHECK_CLASS_CAST( \
26 (klass), AX_PLATFORM_NODE_AURALINUX_TYPE, AXPlatformNodeAuraLinuxClass))
27 #define IS_AX_PLATFORM_NODE_AURALINUX(obj) \
28 (G_TYPE_CHECK_INSTANCE_TYPE((obj), AX_PLATFORM_NODE_AURALINUX_TYPE))
29 #define IS_AX_PLATFORM_NODE_AURALINUX_CLASS(klass) \
30 (G_TYPE_CHECK_CLASS_TYPE((klass), AX_PLATFORM_NODE_AURALINUX_TYPE))
31 #define AX_PLATFORM_NODE_AURALINUX_GET_CLASS(obj) \
32 (G_TYPE_INSTANCE_GET_CLASS( \
33 (obj), AX_PLATFORM_NODE_AURALINUX_TYPE, AXPlatformNodeAuraLinuxClass))
35 typedef struct _AXPlatformNodeAuraLinuxObject AXPlatformNodeAuraLinuxObject
;
36 typedef struct _AXPlatformNodeAuraLinuxClass AXPlatformNodeAuraLinuxClass
;
38 struct _AXPlatformNodeAuraLinuxObject
{
40 ui::AXPlatformNodeAuraLinux
* m_object
;
43 struct _AXPlatformNodeAuraLinuxClass
{
44 AtkObjectClass parent_class
;
47 GType
ax_platform_node_auralinux_get_type();
49 static gpointer ax_platform_node_auralinux_parent_class
= nullptr;
51 static ui::AXPlatformNodeAuraLinux
* ToAXPlatformNodeAuraLinux(
52 AXPlatformNodeAuraLinuxObject
* atk_object
) {
56 return atk_object
->m_object
;
59 static ui::AXPlatformNodeAuraLinux
* AtkObjectToAXPlatformNodeAuraLinux(
60 AtkObject
* atk_object
) {
64 if (IS_AX_PLATFORM_NODE_AURALINUX(atk_object
))
65 return ToAXPlatformNodeAuraLinux(AX_PLATFORM_NODE_AURALINUX(atk_object
));
70 static const gchar
* ax_platform_node_auralinux_get_name(AtkObject
* atk_object
) {
71 ui::AXPlatformNodeAuraLinux
* obj
=
72 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
76 return obj
->GetStringAttribute(ui::AX_ATTR_NAME
).c_str();
79 static const gchar
* ax_platform_node_auralinux_get_description(
80 AtkObject
* atk_object
) {
81 ui::AXPlatformNodeAuraLinux
* obj
=
82 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
86 return obj
->GetStringAttribute(
87 ui::AX_ATTR_DESCRIPTION
).c_str();
90 static gint
ax_platform_node_auralinux_get_index_in_parent(
91 AtkObject
* atk_object
) {
92 ui::AXPlatformNodeAuraLinux
* obj
=
93 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
95 if (!obj
|| !obj
->GetParent())
98 AtkObject
* obj_parent
= obj
->GetParent();
100 unsigned child_count
= atk_object_get_n_accessible_children(obj_parent
);
101 for (unsigned index
= 0; index
< child_count
; index
++) {
102 AtkObject
* child
= atk_object_ref_accessible_child(obj_parent
, index
);
103 bool atk_object_found
= child
== atk_object
;
104 g_object_unref(child
);
105 if (atk_object_found
)
109 return obj
->GetIndexInParent();
112 static AtkObject
* ax_platform_node_auralinux_get_parent(AtkObject
* atk_object
) {
113 ui::AXPlatformNodeAuraLinux
* obj
=
114 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
118 return obj
->GetParent();
121 static gint
ax_platform_node_auralinux_get_n_children(AtkObject
* atk_object
) {
122 ui::AXPlatformNodeAuraLinux
* obj
=
123 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
127 return obj
->GetChildCount();
130 static AtkObject
* ax_platform_node_auralinux_ref_child(
131 AtkObject
* atk_object
, gint index
) {
132 ui::AXPlatformNodeAuraLinux
* obj
=
133 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
137 AtkObject
* result
= obj
->ChildAtIndex(index
);
139 g_object_ref(result
);
143 static AtkRelationSet
* ax_platform_node_auralinux_ref_relation_set(
144 AtkObject
* atk_object
) {
145 ui::AXPlatformNodeAuraLinux
* obj
=
146 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
147 AtkRelationSet
* atk_relation_set
=
148 ATK_OBJECT_CLASS(ax_platform_node_auralinux_parent_class
)->
149 ref_relation_set(atk_object
);
152 return atk_relation_set
;
154 obj
->GetAtkRelations(atk_relation_set
);
155 return atk_relation_set
;
158 static AtkAttributeSet
* ax_platform_node_auralinux_get_attributes(
159 AtkObject
* atk_object
) {
163 static AtkRole
ax_platform_node_auralinux_get_role(AtkObject
* atk_object
) {
164 ui::AXPlatformNodeAuraLinux
* obj
=
165 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
167 return ATK_ROLE_INVALID
;
168 return obj
->GetAtkRole();
171 static AtkStateSet
* ax_platform_node_auralinux_ref_state_set(
172 AtkObject
* atk_object
) {
173 ui::AXPlatformNodeAuraLinux
* obj
=
174 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
178 AtkStateSet
* atk_state_set
=
179 ATK_OBJECT_CLASS(ax_platform_node_auralinux_parent_class
)->
180 ref_state_set(atk_object
);
182 obj
->GetAtkState(atk_state_set
);
183 return atk_state_set
;
187 // AtkComponent interface
190 static gfx::Point
FindAtkObjectParentCoords(AtkObject
* atk_object
) {
192 return gfx::Point(0, 0);
194 if (atk_object_get_role(atk_object
) == ATK_ROLE_WINDOW
) {
196 atk_component_get_extents(ATK_COMPONENT(atk_object
),
197 &x
, &y
, nullptr, nullptr, ATK_XY_WINDOW
);
198 gfx::Point
window_coords(x
, y
);
199 return window_coords
;
201 atk_object
= atk_object_get_parent(atk_object
);
203 return FindAtkObjectParentCoords(atk_object
);
206 static void ax_platform_node_auralinux_get_extents(AtkComponent
* atk_component
,
208 gint
* width
, gint
* height
,
209 AtkCoordType coord_type
) {
210 g_return_if_fail(ATK_IS_COMPONENT(atk_component
));
221 AtkObject
* atk_object
= ATK_OBJECT(atk_component
);
222 ui::AXPlatformNodeAuraLinux
* obj
=
223 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
227 obj
->GetExtents(x
, y
, width
, height
, coord_type
);
230 static void ax_platform_node_auralinux_get_position(AtkComponent
* atk_component
,
232 AtkCoordType coord_type
) {
233 g_return_if_fail(ATK_IS_COMPONENT(atk_component
));
240 AtkObject
* atk_object
= ATK_OBJECT(atk_component
);
241 ui::AXPlatformNodeAuraLinux
* obj
=
242 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
246 obj
->GetPosition(x
, y
, coord_type
);
249 static void ax_platform_node_auralinux_get_size(AtkComponent
* atk_component
,
250 gint
* width
, gint
* height
) {
251 g_return_if_fail(ATK_IS_COMPONENT(atk_component
));
258 AtkObject
* atk_object
= ATK_OBJECT(atk_component
);
259 ui::AXPlatformNodeAuraLinux
* obj
=
260 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
264 obj
->GetSize(width
, height
);
267 void ax_component_interface_base_init(AtkComponentIface
* iface
) {
268 iface
->get_extents
= ax_platform_node_auralinux_get_extents
;
269 iface
->get_position
= ax_platform_node_auralinux_get_position
;
270 iface
->get_size
= ax_platform_node_auralinux_get_size
;
273 static const GInterfaceInfo ComponentInfo
= {
274 reinterpret_cast<GInterfaceInitFunc
>(ax_component_interface_base_init
), 0, 0
278 // The rest of the AXPlatformNodeAuraLinux code, not specific to one
279 // of the Atk* interfaces.
282 static void ax_platform_node_auralinux_init(AtkObject
* atk_object
,
284 if (ATK_OBJECT_CLASS(ax_platform_node_auralinux_parent_class
)->initialize
) {
285 ATK_OBJECT_CLASS(ax_platform_node_auralinux_parent_class
)->initialize(
289 AX_PLATFORM_NODE_AURALINUX(atk_object
)->m_object
=
290 reinterpret_cast<ui::AXPlatformNodeAuraLinux
*>(data
);
293 static void ax_platform_node_auralinux_finalize(GObject
* atk_object
) {
294 G_OBJECT_CLASS(ax_platform_node_auralinux_parent_class
)->finalize(atk_object
);
297 static void ax_platform_node_auralinux_class_init(AtkObjectClass
* klass
) {
298 GObjectClass
* gobject_class
= G_OBJECT_CLASS(klass
);
299 ax_platform_node_auralinux_parent_class
= g_type_class_peek_parent(klass
);
301 gobject_class
->finalize
= ax_platform_node_auralinux_finalize
;
302 klass
->initialize
= ax_platform_node_auralinux_init
;
303 klass
->get_name
= ax_platform_node_auralinux_get_name
;
304 klass
->get_description
= ax_platform_node_auralinux_get_description
;
305 klass
->get_parent
= ax_platform_node_auralinux_get_parent
;
306 klass
->get_n_children
= ax_platform_node_auralinux_get_n_children
;
307 klass
->ref_child
= ax_platform_node_auralinux_ref_child
;
308 klass
->get_role
= ax_platform_node_auralinux_get_role
;
309 klass
->ref_state_set
= ax_platform_node_auralinux_ref_state_set
;
310 klass
->get_index_in_parent
= ax_platform_node_auralinux_get_index_in_parent
;
311 klass
->ref_relation_set
= ax_platform_node_auralinux_ref_relation_set
;
312 klass
->get_attributes
= ax_platform_node_auralinux_get_attributes
;
315 GType
ax_platform_node_auralinux_get_type() {
316 static volatile gsize type_volatile
= 0;
318 if (g_once_init_enter(&type_volatile
)) {
319 static const GTypeInfo tinfo
= {
320 sizeof(AXPlatformNodeAuraLinuxClass
),
322 (GBaseFinalizeFunc
) 0,
323 (GClassInitFunc
) ax_platform_node_auralinux_class_init
,
324 (GClassFinalizeFunc
) 0,
326 sizeof(AXPlatformNodeAuraLinuxObject
), /* instance size */
327 0, /* nb preallocs */
328 (GInstanceInitFunc
) 0,
332 GType type
= g_type_register_static(
333 ATK_TYPE_OBJECT
, "AXPlatformNodeAuraLinux", &tinfo
, GTypeFlags(0));
334 g_type_add_interface_static(type
, ATK_TYPE_COMPONENT
, &ComponentInfo
);
335 g_once_init_leave(&type_volatile
, type
);
338 return type_volatile
;
341 AXPlatformNodeAuraLinuxObject
* ax_platform_node_auralinux_new(
342 ui::AXPlatformNodeAuraLinux
* obj
) {
343 #if !GLIB_CHECK_VERSION(2, 36, 0)
344 static bool first_time
= true;
351 GType type
= AX_PLATFORM_NODE_AURALINUX_TYPE
;
352 AtkObject
* atk_object
= static_cast<AtkObject
*>(g_object_new(type
, 0));
353 atk_object_initialize(atk_object
, obj
);
354 return AX_PLATFORM_NODE_AURALINUX(atk_object
);
357 void ax_platform_node_auralinux_detach(
358 AXPlatformNodeAuraLinuxObject
* atk_object
) {
359 atk_object
->m_object
= nullptr;
365 // AXPlatformNodeAuraLinux implementation.
371 AXPlatformNode
* AXPlatformNode::Create(AXPlatformNodeDelegate
* delegate
) {
372 AXPlatformNodeAuraLinux
* node
= new AXPlatformNodeAuraLinux();
373 node
->Init(delegate
);
378 AXPlatformNode
* AXPlatformNodeAuraLinux::application_
= nullptr;
381 void AXPlatformNodeAuraLinux::SetApplication(AXPlatformNode
* application
) {
382 application_
= application
;
386 void AXPlatformNodeAuraLinux::StaticInitialize(
387 scoped_refptr
<base::TaskRunner
> init_task_runner
) {
388 AtkUtilAuraLinux::GetInstance()->Initialize(init_task_runner
);
391 AtkRole
AXPlatformNodeAuraLinux::GetAtkRole() {
392 switch (GetData().role
) {
393 case ui::AX_ROLE_ALERT
:
394 return ATK_ROLE_ALERT
;
395 case ui::AX_ROLE_APPLICATION
:
396 return ATK_ROLE_APPLICATION
;
397 case ui::AX_ROLE_BUTTON
:
398 return ATK_ROLE_PUSH_BUTTON
;
399 case ui::AX_ROLE_CHECK_BOX
:
400 return ATK_ROLE_CHECK_BOX
;
401 case ui::AX_ROLE_COMBO_BOX
:
402 return ATK_ROLE_COMBO_BOX
;
403 case ui::AX_ROLE_DIALOG
:
404 return ATK_ROLE_DIALOG
;
405 case ui::AX_ROLE_GROUP
:
406 return ATK_ROLE_PANEL
;
407 case ui::AX_ROLE_IMAGE
:
408 return ATK_ROLE_IMAGE
;
409 case ui::AX_ROLE_MENU_ITEM
:
410 return ATK_ROLE_MENU_ITEM
;
411 case ui::AX_ROLE_SCROLL_BAR
:
412 return ATK_ROLE_SCROLL_BAR
;
413 case ui::AX_ROLE_SLIDER
:
414 return ATK_ROLE_SLIDER
;
415 case ui::AX_ROLE_SPLITTER
:
416 return ATK_ROLE_SEPARATOR
;
417 case ui::AX_ROLE_STATIC_TEXT
:
418 return ATK_ROLE_TEXT
;
419 case ui::AX_ROLE_TAB
:
420 return ATK_ROLE_PAGE_TAB
;
421 case ui::AX_ROLE_TAB_LIST
:
422 return ATK_ROLE_PAGE_TAB_LIST
;
423 case ui::AX_ROLE_TEXT_FIELD
:
424 return ATK_ROLE_ENTRY
;
425 case ui::AX_ROLE_TOOLBAR
:
426 return ATK_ROLE_TOOL_BAR
;
427 case ui::AX_ROLE_WINDOW
:
428 return ATK_ROLE_WINDOW
;
430 return ATK_ROLE_UNKNOWN
;
434 void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet
* atk_state_set
) {
435 uint32 state
= GetData().state
;
437 if (state
& (1 << ui::AX_STATE_CHECKED
))
438 atk_state_set_add_state(atk_state_set
, ATK_STATE_CHECKED
);
439 if (state
& (1 << ui::AX_STATE_DEFAULT
))
440 atk_state_set_add_state(atk_state_set
, ATK_STATE_DEFAULT
);
441 if (state
& (1 << ui::AX_STATE_EDITABLE
))
442 atk_state_set_add_state(atk_state_set
, ATK_STATE_EDITABLE
);
443 if (state
& (1 << ui::AX_STATE_ENABLED
))
444 atk_state_set_add_state(atk_state_set
, ATK_STATE_ENABLED
);
445 if (state
& (1 << ui::AX_STATE_EXPANDED
))
446 atk_state_set_add_state(atk_state_set
, ATK_STATE_EXPANDED
);
447 if (state
& (1 << ui::AX_STATE_FOCUSABLE
))
448 atk_state_set_add_state(atk_state_set
, ATK_STATE_FOCUSABLE
);
449 if (state
& (1 << ui::AX_STATE_FOCUSED
))
450 atk_state_set_add_state(atk_state_set
, ATK_STATE_FOCUSED
);
451 if (state
& (1 << ui::AX_STATE_PRESSED
))
452 atk_state_set_add_state(atk_state_set
, ATK_STATE_PRESSED
);
453 if (state
& (1 << ui::AX_STATE_SELECTABLE
))
454 atk_state_set_add_state(atk_state_set
, ATK_STATE_SELECTABLE
);
455 if (state
& (1 << ui::AX_STATE_SELECTED
))
456 atk_state_set_add_state(atk_state_set
, ATK_STATE_SELECTED
);
459 void AXPlatformNodeAuraLinux::GetAtkRelations(AtkRelationSet
* atk_relation_set
)
463 AXPlatformNodeAuraLinux::AXPlatformNodeAuraLinux()
464 : atk_object_(nullptr) {
467 AXPlatformNodeAuraLinux::~AXPlatformNodeAuraLinux() {
468 g_object_unref(atk_object_
);
471 void AXPlatformNodeAuraLinux::Init(AXPlatformNodeDelegate
* delegate
) {
473 AXPlatformNodeBase::Init(delegate
);
474 atk_object_
= ATK_OBJECT(ax_platform_node_auralinux_new(this));
477 void AXPlatformNodeAuraLinux::Destroy() {
482 gfx::NativeViewAccessible
AXPlatformNodeAuraLinux::GetNativeViewAccessible() {
486 void AXPlatformNodeAuraLinux::NotifyAccessibilityEvent(ui::AXEvent event_type
) {
489 int AXPlatformNodeAuraLinux::GetIndexInParent() {
493 void AXPlatformNodeAuraLinux::SetExtentsRelativeToAtkCoordinateType(
494 gint
* x
, gint
* y
, gint
* width
, gint
* height
, AtkCoordType coord_type
) {
495 gfx::Rect extents
= GetBoundsInScreen();
502 *width
= extents
.width();
504 *height
= extents
.height();
506 if (coord_type
== ATK_XY_WINDOW
) {
507 if (AtkObject
* atk_object
= GetParent()) {
508 gfx::Point window_coords
= FindAtkObjectParentCoords(atk_object
);
510 *x
-= window_coords
.x();
512 *y
-= window_coords
.y();
517 void AXPlatformNodeAuraLinux::GetExtents(gint
* x
, gint
* y
,
518 gint
* width
, gint
* height
,
519 AtkCoordType coord_type
) {
520 SetExtentsRelativeToAtkCoordinateType(x
, y
,
525 void AXPlatformNodeAuraLinux::GetPosition(gint
* x
, gint
* y
,
526 AtkCoordType coord_type
) {
527 SetExtentsRelativeToAtkCoordinateType(x
, y
,
532 void AXPlatformNodeAuraLinux::GetSize(gint
* width
, gint
* height
) {
533 gfx::Rect rect_size
= GetData().location
;
535 *width
= rect_size
.width();
537 *height
= rect_size
.height();