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
) {
191 if (atk_object_get_role(atk_object
) == ATK_ROLE_WINDOW
) {
193 atk_component_get_extents(ATK_COMPONENT(atk_object
),
194 &x
, &y
, nullptr, nullptr, ATK_XY_WINDOW
);
195 gfx::Point
window_coords(x
, y
);
196 return window_coords
;
198 atk_object
= atk_object_get_parent(atk_object
);
200 return FindAtkObjectParentCoords(atk_object
);
203 static void ax_platform_node_auralinux_get_extents(AtkComponent
* atk_component
,
205 gint
* width
, gint
* height
,
206 AtkCoordType coord_type
) {
207 g_return_if_fail(ATK_IS_COMPONENT(atk_component
));
218 AtkObject
* atk_object
= ATK_OBJECT(atk_component
);
219 ui::AXPlatformNodeAuraLinux
* obj
=
220 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
224 obj
->GetExtents(x
, y
, width
, height
, coord_type
);
227 static void ax_platform_node_auralinux_get_position(AtkComponent
* atk_component
,
229 AtkCoordType coord_type
) {
230 g_return_if_fail(ATK_IS_COMPONENT(atk_component
));
237 AtkObject
* atk_object
= ATK_OBJECT(atk_component
);
238 ui::AXPlatformNodeAuraLinux
* obj
=
239 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
243 obj
->GetPosition(x
, y
, coord_type
);
246 static void ax_platform_node_auralinux_get_size(AtkComponent
* atk_component
,
247 gint
* width
, gint
* height
) {
248 g_return_if_fail(ATK_IS_COMPONENT(atk_component
));
255 AtkObject
* atk_object
= ATK_OBJECT(atk_component
);
256 ui::AXPlatformNodeAuraLinux
* obj
=
257 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
261 obj
->GetSize(width
, height
);
264 void ax_component_interface_base_init(AtkComponentIface
* iface
) {
265 iface
->get_extents
= ax_platform_node_auralinux_get_extents
;
266 iface
->get_position
= ax_platform_node_auralinux_get_position
;
267 iface
->get_size
= ax_platform_node_auralinux_get_size
;
270 static const GInterfaceInfo ComponentInfo
= {
271 reinterpret_cast<GInterfaceInitFunc
>(ax_component_interface_base_init
), 0, 0
275 // The rest of the AXPlatformNodeAuraLinux code, not specific to one
276 // of the Atk* interfaces.
279 static void ax_platform_node_auralinux_init(AtkObject
* atk_object
,
281 if (ATK_OBJECT_CLASS(ax_platform_node_auralinux_parent_class
)->initialize
) {
282 ATK_OBJECT_CLASS(ax_platform_node_auralinux_parent_class
)->initialize(
286 AX_PLATFORM_NODE_AURALINUX(atk_object
)->m_object
=
287 reinterpret_cast<ui::AXPlatformNodeAuraLinux
*>(data
);
290 static void ax_platform_node_auralinux_finalize(GObject
* atk_object
) {
291 G_OBJECT_CLASS(ax_platform_node_auralinux_parent_class
)->finalize(atk_object
);
294 static void ax_platform_node_auralinux_class_init(AtkObjectClass
* klass
) {
295 GObjectClass
* gobject_class
= G_OBJECT_CLASS(klass
);
296 ax_platform_node_auralinux_parent_class
= g_type_class_peek_parent(klass
);
298 gobject_class
->finalize
= ax_platform_node_auralinux_finalize
;
299 klass
->initialize
= ax_platform_node_auralinux_init
;
300 klass
->get_name
= ax_platform_node_auralinux_get_name
;
301 klass
->get_description
= ax_platform_node_auralinux_get_description
;
302 klass
->get_parent
= ax_platform_node_auralinux_get_parent
;
303 klass
->get_n_children
= ax_platform_node_auralinux_get_n_children
;
304 klass
->ref_child
= ax_platform_node_auralinux_ref_child
;
305 klass
->get_role
= ax_platform_node_auralinux_get_role
;
306 klass
->ref_state_set
= ax_platform_node_auralinux_ref_state_set
;
307 klass
->get_index_in_parent
= ax_platform_node_auralinux_get_index_in_parent
;
308 klass
->ref_relation_set
= ax_platform_node_auralinux_ref_relation_set
;
309 klass
->get_attributes
= ax_platform_node_auralinux_get_attributes
;
312 GType
ax_platform_node_auralinux_get_type() {
313 static volatile gsize type_volatile
= 0;
315 if (g_once_init_enter(&type_volatile
)) {
316 static const GTypeInfo tinfo
= {
317 sizeof(AXPlatformNodeAuraLinuxClass
),
319 (GBaseFinalizeFunc
) 0,
320 (GClassInitFunc
) ax_platform_node_auralinux_class_init
,
321 (GClassFinalizeFunc
) 0,
323 sizeof(AXPlatformNodeAuraLinuxObject
), /* instance size */
324 0, /* nb preallocs */
325 (GInstanceInitFunc
) 0,
329 GType type
= g_type_register_static(
330 ATK_TYPE_OBJECT
, "AXPlatformNodeAuraLinux", &tinfo
, GTypeFlags(0));
331 g_type_add_interface_static(type
, ATK_TYPE_COMPONENT
, &ComponentInfo
);
332 g_once_init_leave(&type_volatile
, type
);
335 return type_volatile
;
338 AXPlatformNodeAuraLinuxObject
* ax_platform_node_auralinux_new(
339 ui::AXPlatformNodeAuraLinux
* obj
) {
340 #if !GLIB_CHECK_VERSION(2, 36, 0)
341 static bool first_time
= true;
348 GType type
= AX_PLATFORM_NODE_AURALINUX_TYPE
;
349 AtkObject
* atk_object
= static_cast<AtkObject
*>(g_object_new(type
, 0));
350 atk_object_initialize(atk_object
, obj
);
351 return AX_PLATFORM_NODE_AURALINUX(atk_object
);
354 void ax_platform_node_auralinux_detach(
355 AXPlatformNodeAuraLinuxObject
* atk_object
) {
356 atk_object
->m_object
= nullptr;
362 // AXPlatformNodeAuraLinux implementation.
368 AXPlatformNode
* AXPlatformNode::Create(AXPlatformNodeDelegate
* delegate
) {
369 AXPlatformNodeAuraLinux
* node
= new AXPlatformNodeAuraLinux();
370 node
->Init(delegate
);
375 AXPlatformNode
* AXPlatformNodeAuraLinux::application_
= nullptr;
378 void AXPlatformNodeAuraLinux::SetApplication(AXPlatformNode
* application
) {
379 application_
= application
;
383 void AXPlatformNodeAuraLinux::StaticInitialize(
384 scoped_refptr
<base::TaskRunner
> init_task_runner
) {
385 AtkUtilAuraLinux::GetInstance()->Initialize(init_task_runner
);
388 AtkRole
AXPlatformNodeAuraLinux::GetAtkRole() {
389 switch (GetData().role
) {
390 case ui::AX_ROLE_ALERT
:
391 return ATK_ROLE_ALERT
;
392 case ui::AX_ROLE_APPLICATION
:
393 return ATK_ROLE_APPLICATION
;
394 case ui::AX_ROLE_BUTTON
:
395 return ATK_ROLE_PUSH_BUTTON
;
396 case ui::AX_ROLE_CHECK_BOX
:
397 return ATK_ROLE_CHECK_BOX
;
398 case ui::AX_ROLE_COMBO_BOX
:
399 return ATK_ROLE_COMBO_BOX
;
400 case ui::AX_ROLE_DIALOG
:
401 return ATK_ROLE_DIALOG
;
402 case ui::AX_ROLE_GROUP
:
403 return ATK_ROLE_PANEL
;
404 case ui::AX_ROLE_IMAGE
:
405 return ATK_ROLE_IMAGE
;
406 case ui::AX_ROLE_MENU_ITEM
:
407 return ATK_ROLE_MENU_ITEM
;
408 case ui::AX_ROLE_SCROLL_BAR
:
409 return ATK_ROLE_SCROLL_BAR
;
410 case ui::AX_ROLE_SLIDER
:
411 return ATK_ROLE_SLIDER
;
412 case ui::AX_ROLE_SPLITTER
:
413 return ATK_ROLE_SEPARATOR
;
414 case ui::AX_ROLE_STATIC_TEXT
:
415 return ATK_ROLE_TEXT
;
416 case ui::AX_ROLE_TAB
:
417 return ATK_ROLE_PAGE_TAB
;
418 case ui::AX_ROLE_TAB_LIST
:
419 return ATK_ROLE_PAGE_TAB_LIST
;
420 case ui::AX_ROLE_TEXT_FIELD
:
421 return ATK_ROLE_ENTRY
;
422 case ui::AX_ROLE_TOOLBAR
:
423 return ATK_ROLE_TOOL_BAR
;
424 case ui::AX_ROLE_WINDOW
:
425 return ATK_ROLE_WINDOW
;
427 return ATK_ROLE_UNKNOWN
;
431 void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet
* atk_state_set
) {
432 uint32 state
= GetData().state
;
434 if (state
& (1 << ui::AX_STATE_CHECKED
))
435 atk_state_set_add_state(atk_state_set
, ATK_STATE_CHECKED
);
436 if (state
& (1 << ui::AX_STATE_DEFAULT
))
437 atk_state_set_add_state(atk_state_set
, ATK_STATE_DEFAULT
);
438 if (state
& (1 << ui::AX_STATE_EDITABLE
))
439 atk_state_set_add_state(atk_state_set
, ATK_STATE_EDITABLE
);
440 if (state
& (1 << ui::AX_STATE_ENABLED
))
441 atk_state_set_add_state(atk_state_set
, ATK_STATE_ENABLED
);
442 if (state
& (1 << ui::AX_STATE_EXPANDED
))
443 atk_state_set_add_state(atk_state_set
, ATK_STATE_EXPANDED
);
444 if (state
& (1 << ui::AX_STATE_FOCUSABLE
))
445 atk_state_set_add_state(atk_state_set
, ATK_STATE_FOCUSABLE
);
446 if (state
& (1 << ui::AX_STATE_FOCUSED
))
447 atk_state_set_add_state(atk_state_set
, ATK_STATE_FOCUSED
);
448 if (state
& (1 << ui::AX_STATE_PRESSED
))
449 atk_state_set_add_state(atk_state_set
, ATK_STATE_PRESSED
);
450 if (state
& (1 << ui::AX_STATE_SELECTABLE
))
451 atk_state_set_add_state(atk_state_set
, ATK_STATE_SELECTABLE
);
452 if (state
& (1 << ui::AX_STATE_SELECTED
))
453 atk_state_set_add_state(atk_state_set
, ATK_STATE_SELECTED
);
456 void AXPlatformNodeAuraLinux::GetAtkRelations(AtkRelationSet
* atk_relation_set
)
460 AXPlatformNodeAuraLinux::AXPlatformNodeAuraLinux()
461 : atk_object_(nullptr) {
464 AXPlatformNodeAuraLinux::~AXPlatformNodeAuraLinux() {
465 g_object_unref(atk_object_
);
468 void AXPlatformNodeAuraLinux::Init(AXPlatformNodeDelegate
* delegate
) {
470 AXPlatformNodeBase::Init(delegate
);
471 atk_object_
= ATK_OBJECT(ax_platform_node_auralinux_new(this));
474 void AXPlatformNodeAuraLinux::Destroy() {
479 gfx::NativeViewAccessible
AXPlatformNodeAuraLinux::GetNativeViewAccessible() {
483 void AXPlatformNodeAuraLinux::NotifyAccessibilityEvent(ui::AXEvent event_type
) {
486 int AXPlatformNodeAuraLinux::GetIndexInParent() {
490 void AXPlatformNodeAuraLinux::SetExtentsRelativeToAtkCoordinateType(
491 gint
* x
, gint
* y
, gint
* width
, gint
* height
, AtkCoordType coord_type
) {
492 gfx::Rect extents
= GetBoundsInScreen();
499 *width
= extents
.width();
501 *height
= extents
.height();
503 if (coord_type
== ATK_XY_WINDOW
) {
504 AtkObject
* atk_object
= GetParent();
505 gfx::Point window_coords
= FindAtkObjectParentCoords(atk_object
);
507 *x
-= window_coords
.x();
509 *y
-= window_coords
.y();
513 void AXPlatformNodeAuraLinux::GetExtents(gint
* x
, gint
* y
,
514 gint
* width
, gint
* height
,
515 AtkCoordType coord_type
) {
516 SetExtentsRelativeToAtkCoordinateType(x
, y
,
521 void AXPlatformNodeAuraLinux::GetPosition(gint
* x
, gint
* y
,
522 AtkCoordType coord_type
) {
523 SetExtentsRelativeToAtkCoordinateType(x
, y
,
528 void AXPlatformNodeAuraLinux::GetSize(gint
* width
, gint
* height
) {
529 gfx::Rect rect_size
= GetData().location
;
531 *width
= rect_size
.width();
533 *height
= rect_size
.height();