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_position(ATK_COMPONENT(atk_object
),
194 &x
, &y
, 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 *x
= *y
= *width
= *height
= 0;
208 AtkObject
* atk_object
= ATK_OBJECT(atk_component
);
209 ui::AXPlatformNodeAuraLinux
* obj
=
210 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
214 obj
->GetExtents(x
, y
, width
, height
, coord_type
);
217 static void ax_platform_node_auralinux_get_position(AtkComponent
* atk_component
,
219 AtkCoordType coord_type
) {
221 AtkObject
* atk_object
= ATK_OBJECT(atk_component
);
222 ui::AXPlatformNodeAuraLinux
* obj
=
223 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
227 obj
->GetPosition(x
, y
, coord_type
);
230 static void ax_platform_node_auralinux_get_size(AtkComponent
* atk_component
,
231 gint
* width
, gint
* height
) {
232 *width
= *height
= 0;
233 AtkObject
* atk_object
= ATK_OBJECT(atk_component
);
234 ui::AXPlatformNodeAuraLinux
* obj
=
235 AtkObjectToAXPlatformNodeAuraLinux(atk_object
);
239 obj
->GetSize(width
, height
);
242 void ax_component_interface_base_init(AtkComponentIface
* iface
) {
243 iface
->get_extents
= ax_platform_node_auralinux_get_extents
;
244 iface
->get_position
= ax_platform_node_auralinux_get_position
;
245 iface
->get_size
= ax_platform_node_auralinux_get_size
;
248 static const GInterfaceInfo ComponentInfo
= {
249 reinterpret_cast<GInterfaceInitFunc
>(ax_component_interface_base_init
), 0, 0
253 // The rest of the AXPlatformNodeAuraLinux code, not specific to one
254 // of the Atk* interfaces.
257 static void ax_platform_node_auralinux_init(AtkObject
* atk_object
,
259 if (ATK_OBJECT_CLASS(ax_platform_node_auralinux_parent_class
)->initialize
) {
260 ATK_OBJECT_CLASS(ax_platform_node_auralinux_parent_class
)->initialize(
264 AX_PLATFORM_NODE_AURALINUX(atk_object
)->m_object
=
265 reinterpret_cast<ui::AXPlatformNodeAuraLinux
*>(data
);
268 static void ax_platform_node_auralinux_finalize(GObject
* atk_object
) {
269 G_OBJECT_CLASS(ax_platform_node_auralinux_parent_class
)->finalize(atk_object
);
272 static void ax_platform_node_auralinux_class_init(AtkObjectClass
* klass
) {
273 GObjectClass
* gobject_class
= G_OBJECT_CLASS(klass
);
274 ax_platform_node_auralinux_parent_class
= g_type_class_peek_parent(klass
);
276 gobject_class
->finalize
= ax_platform_node_auralinux_finalize
;
277 klass
->initialize
= ax_platform_node_auralinux_init
;
278 klass
->get_name
= ax_platform_node_auralinux_get_name
;
279 klass
->get_description
= ax_platform_node_auralinux_get_description
;
280 klass
->get_parent
= ax_platform_node_auralinux_get_parent
;
281 klass
->get_n_children
= ax_platform_node_auralinux_get_n_children
;
282 klass
->ref_child
= ax_platform_node_auralinux_ref_child
;
283 klass
->get_role
= ax_platform_node_auralinux_get_role
;
284 klass
->ref_state_set
= ax_platform_node_auralinux_ref_state_set
;
285 klass
->get_index_in_parent
= ax_platform_node_auralinux_get_index_in_parent
;
286 klass
->ref_relation_set
= ax_platform_node_auralinux_ref_relation_set
;
287 klass
->get_attributes
= ax_platform_node_auralinux_get_attributes
;
290 GType
ax_platform_node_auralinux_get_type() {
291 static volatile gsize type_volatile
= 0;
293 if (g_once_init_enter(&type_volatile
)) {
294 static const GTypeInfo tinfo
= {
295 sizeof(AXPlatformNodeAuraLinuxClass
),
297 (GBaseFinalizeFunc
) 0,
298 (GClassInitFunc
) ax_platform_node_auralinux_class_init
,
299 (GClassFinalizeFunc
) 0,
301 sizeof(AXPlatformNodeAuraLinuxObject
), /* instance size */
302 0, /* nb preallocs */
303 (GInstanceInitFunc
) 0,
307 GType type
= g_type_register_static(
308 ATK_TYPE_OBJECT
, "AXPlatformNodeAuraLinux", &tinfo
, GTypeFlags(0));
309 g_type_add_interface_static(type
, ATK_TYPE_COMPONENT
, &ComponentInfo
);
310 g_once_init_leave(&type_volatile
, type
);
313 return type_volatile
;
316 AXPlatformNodeAuraLinuxObject
* ax_platform_node_auralinux_new(
317 ui::AXPlatformNodeAuraLinux
* obj
) {
318 #if !GLIB_CHECK_VERSION(2, 36, 0)
319 static bool first_time
= true;
326 GType type
= AX_PLATFORM_NODE_AURALINUX_TYPE
;
327 AtkObject
* atk_object
= static_cast<AtkObject
*>(g_object_new(type
, 0));
328 atk_object_initialize(atk_object
, obj
);
329 return AX_PLATFORM_NODE_AURALINUX(atk_object
);
332 void ax_platform_node_auralinux_detach(
333 AXPlatformNodeAuraLinuxObject
* atk_object
) {
334 atk_object
->m_object
= nullptr;
340 // AXPlatformNodeAuraLinux implementation.
346 AXPlatformNode
* AXPlatformNode::Create(AXPlatformNodeDelegate
* delegate
) {
347 AXPlatformNodeAuraLinux
* node
= new AXPlatformNodeAuraLinux();
348 node
->Init(delegate
);
353 AXPlatformNode
* AXPlatformNodeAuraLinux::application_
= nullptr;
356 void AXPlatformNodeAuraLinux::SetApplication(AXPlatformNode
* application
) {
357 application_
= application
;
361 void AXPlatformNodeAuraLinux::StaticInitialize(
362 scoped_refptr
<base::TaskRunner
> init_task_runner
) {
363 AtkUtilAuraLinux::GetInstance()->Initialize(init_task_runner
);
366 AtkRole
AXPlatformNodeAuraLinux::GetAtkRole() {
367 switch (GetData().role
) {
368 case ui::AX_ROLE_ALERT
:
369 return ATK_ROLE_ALERT
;
370 case ui::AX_ROLE_APPLICATION
:
371 return ATK_ROLE_APPLICATION
;
372 case ui::AX_ROLE_BUTTON
:
373 return ATK_ROLE_PUSH_BUTTON
;
374 case ui::AX_ROLE_CHECK_BOX
:
375 return ATK_ROLE_CHECK_BOX
;
376 case ui::AX_ROLE_COMBO_BOX
:
377 return ATK_ROLE_COMBO_BOX
;
378 case ui::AX_ROLE_DIALOG
:
379 return ATK_ROLE_DIALOG
;
380 case ui::AX_ROLE_GROUP
:
381 return ATK_ROLE_PANEL
;
382 case ui::AX_ROLE_IMAGE
:
383 return ATK_ROLE_IMAGE
;
384 case ui::AX_ROLE_MENU_ITEM
:
385 return ATK_ROLE_MENU_ITEM
;
386 case ui::AX_ROLE_SCROLL_BAR
:
387 return ATK_ROLE_SCROLL_BAR
;
388 case ui::AX_ROLE_SLIDER
:
389 return ATK_ROLE_SLIDER
;
390 case ui::AX_ROLE_SPLITTER
:
391 return ATK_ROLE_SEPARATOR
;
392 case ui::AX_ROLE_STATIC_TEXT
:
393 return ATK_ROLE_TEXT
;
394 case ui::AX_ROLE_TAB
:
395 return ATK_ROLE_PAGE_TAB
;
396 case ui::AX_ROLE_TAB_LIST
:
397 return ATK_ROLE_PAGE_TAB_LIST
;
398 case ui::AX_ROLE_TEXT_FIELD
:
399 return ATK_ROLE_ENTRY
;
400 case ui::AX_ROLE_TOOLBAR
:
401 return ATK_ROLE_TOOL_BAR
;
402 case ui::AX_ROLE_WINDOW
:
403 return ATK_ROLE_WINDOW
;
405 return ATK_ROLE_UNKNOWN
;
409 void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet
* atk_state_set
) {
410 uint32 state
= GetData().state
;
412 if (state
& (1 << ui::AX_STATE_CHECKED
))
413 atk_state_set_add_state(atk_state_set
, ATK_STATE_CHECKED
);
414 if (state
& (1 << ui::AX_STATE_DEFAULT
))
415 atk_state_set_add_state(atk_state_set
, ATK_STATE_DEFAULT
);
416 if (state
& (1 << ui::AX_STATE_EDITABLE
))
417 atk_state_set_add_state(atk_state_set
, ATK_STATE_EDITABLE
);
418 if (state
& (1 << ui::AX_STATE_ENABLED
))
419 atk_state_set_add_state(atk_state_set
, ATK_STATE_ENABLED
);
420 if (state
& (1 << ui::AX_STATE_EXPANDED
))
421 atk_state_set_add_state(atk_state_set
, ATK_STATE_EXPANDED
);
422 if (state
& (1 << ui::AX_STATE_FOCUSABLE
))
423 atk_state_set_add_state(atk_state_set
, ATK_STATE_FOCUSABLE
);
424 if (state
& (1 << ui::AX_STATE_FOCUSED
))
425 atk_state_set_add_state(atk_state_set
, ATK_STATE_FOCUSED
);
426 if (state
& (1 << ui::AX_STATE_PRESSED
))
427 atk_state_set_add_state(atk_state_set
, ATK_STATE_PRESSED
);
428 if (state
& (1 << ui::AX_STATE_SELECTABLE
))
429 atk_state_set_add_state(atk_state_set
, ATK_STATE_SELECTABLE
);
430 if (state
& (1 << ui::AX_STATE_SELECTED
))
431 atk_state_set_add_state(atk_state_set
, ATK_STATE_SELECTED
);
434 void AXPlatformNodeAuraLinux::GetAtkRelations(AtkRelationSet
* atk_relation_set
)
438 AXPlatformNodeAuraLinux::AXPlatformNodeAuraLinux()
439 : atk_object_(nullptr) {
442 AXPlatformNodeAuraLinux::~AXPlatformNodeAuraLinux() {
443 g_object_unref(atk_object_
);
446 void AXPlatformNodeAuraLinux::Init(AXPlatformNodeDelegate
* delegate
) {
448 AXPlatformNodeBase::Init(delegate
);
449 atk_object_
= ATK_OBJECT(ax_platform_node_auralinux_new(this));
452 void AXPlatformNodeAuraLinux::Destroy() {
457 gfx::NativeViewAccessible
AXPlatformNodeAuraLinux::GetNativeViewAccessible() {
461 void AXPlatformNodeAuraLinux::NotifyAccessibilityEvent(ui::AXEvent event_type
) {
464 int AXPlatformNodeAuraLinux::GetIndexInParent() {
468 void AXPlatformNodeAuraLinux::GetExtents(gint
* x
, gint
* y
,
469 gint
* width
, gint
* height
,
470 AtkCoordType coord_type
) {
471 gfx::Rect extents
= GetBoundsInScreen();
475 *width
= extents
.width();
476 *height
= extents
.height();
478 if (coord_type
== ATK_XY_WINDOW
) {
479 AtkObject
* atk_object
= GetParent();
480 gfx::Point window_coords
= FindAtkObjectParentCoords(atk_object
);
481 *x
-= window_coords
.x();
482 *y
-= window_coords
.y();
486 void AXPlatformNodeAuraLinux::GetPosition(gint
* x
, gint
* y
,
487 AtkCoordType coord_type
) {
488 gfx::Rect rect_pos
= GetBoundsInScreen();
493 if (coord_type
== ATK_XY_WINDOW
) {
494 AtkObject
* atk_object
= GetParent();
495 gfx::Point window_coords
= FindAtkObjectParentCoords(atk_object
);
496 *x
-= window_coords
.x();
497 *y
-= window_coords
.y();
501 void AXPlatformNodeAuraLinux::GetSize(gint
* width
, gint
* height
) {
502 gfx::Rect rect_size
= GetData().location
;
503 *width
= rect_size
.width();
504 *height
= rect_size
.height();