1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ApplicationAccessibleWrap.h"
11 #include "nsAccessibilityService.h"
16 using namespace mozilla
;
17 using namespace mozilla::a11y
;
19 // ApplicationAccessibleWrap
21 ApplicationAccessibleWrap::ApplicationAccessibleWrap()
22 : ApplicationAccessible() {}
24 ApplicationAccessibleWrap::~ApplicationAccessibleWrap() {
25 AccessibleWrap::ShutdownAtkObject();
28 gboolean
toplevel_event_watcher(GSignalInvocationHint
* ihint
,
30 const GValue
* param_values
, gpointer data
) {
31 static GQuark sQuark_gecko_acc_obj
= 0;
33 if (!sQuark_gecko_acc_obj
) {
34 sQuark_gecko_acc_obj
= g_quark_from_static_string("GeckoAccObj");
37 if (nsAccessibilityService::IsShutdown()) return TRUE
;
40 reinterpret_cast<GObject
*>(g_value_get_object(param_values
));
41 if (!GTK_IS_WINDOW(object
)) return TRUE
;
43 AtkObject
* child
= gtk_widget_get_accessible(GTK_WIDGET(object
));
44 AtkRole role
= atk_object_get_role(child
);
47 if (!IS_MAI_OBJECT(child
) &&
48 (role
== ATK_ROLE_DIALOG
|| role
== ATK_ROLE_FILE_CHOOSER
||
49 role
== ATK_ROLE_COLOR_CHOOSER
|| role
== ATK_ROLE_FONT_CHOOSER
)) {
50 if (data
== reinterpret_cast<gpointer
>(nsIAccessibleEvent::EVENT_SHOW
)) {
51 // Attach the dialog accessible to app accessible tree
52 LocalAccessible
* windowAcc
=
53 GetAccService()->AddNativeRootAccessible(child
);
54 g_object_set_qdata(G_OBJECT(child
), sQuark_gecko_acc_obj
,
55 reinterpret_cast<gpointer
>(windowAcc
));
58 // Deattach the dialog accessible
59 LocalAccessible
* windowAcc
= reinterpret_cast<LocalAccessible
*>(
60 g_object_get_qdata(G_OBJECT(child
), sQuark_gecko_acc_obj
));
62 GetAccService()->RemoveNativeRootAccessible(windowAcc
);
63 g_object_set_qdata(G_OBJECT(child
), sQuark_gecko_acc_obj
, nullptr);
71 ENameValueFlag
ApplicationAccessibleWrap::Name(nsString
& aName
) const {
72 // ATK doesn't provide a way to obtain an application name (for example,
73 // Firefox or Thunderbird) like IA2 does. Thus let's return an application
74 // name as accessible name that was used to get a branding name (for example,
75 // Minefield aka nightly Firefox or Daily aka nightly Thunderbird).
80 void ApplicationAccessibleWrap::GetNativeInterface(void** aOutAccessible
) {
81 *aOutAccessible
= nullptr;
84 mAtkObject
= reinterpret_cast<AtkObject
*>(
85 g_object_new(MAI_TYPE_ATK_OBJECT
, nullptr));
86 if (!mAtkObject
) return;
88 atk_object_initialize(mAtkObject
, static_cast<Accessible
*>(this));
89 mAtkObject
->role
= ATK_ROLE_INVALID
;
90 mAtkObject
->layer
= ATK_LAYER_INVALID
;
93 *aOutAccessible
= mAtkObject
;
96 struct AtkRootAccessibleAddedEvent
{
97 AtkObject
* app_accessible
;
98 AtkObject
* root_accessible
;
102 gboolean
fireRootAccessibleAddedCB(gpointer data
) {
103 AtkRootAccessibleAddedEvent
* eventData
= (AtkRootAccessibleAddedEvent
*)data
;
104 g_signal_emit_by_name(eventData
->app_accessible
, "children_changed::add",
105 eventData
->index
, eventData
->root_accessible
, nullptr);
106 g_object_unref(eventData
->app_accessible
);
107 g_object_unref(eventData
->root_accessible
);
113 bool ApplicationAccessibleWrap::InsertChildAt(uint32_t aIdx
,
114 LocalAccessible
* aChild
) {
115 if (!ApplicationAccessible::InsertChildAt(aIdx
, aChild
)) return false;
117 AtkObject
* atkAccessible
= AccessibleWrap::GetAtkObject(aChild
);
118 atk_object_set_parent(atkAccessible
, mAtkObject
);
120 uint32_t count
= mChildren
.Length();
122 // Emit children_changed::add in a timeout
123 // to make sure aRootAccWrap is fully initialized.
124 AtkRootAccessibleAddedEvent
* eventData
=
125 (AtkRootAccessibleAddedEvent
*)malloc(sizeof(AtkRootAccessibleAddedEvent
));
127 eventData
->app_accessible
= mAtkObject
;
128 eventData
->root_accessible
= atkAccessible
;
129 eventData
->index
= count
- 1;
130 g_object_ref(mAtkObject
);
131 g_object_ref(atkAccessible
);
132 g_timeout_add(0, fireRootAccessibleAddedCB
, eventData
);
138 bool ApplicationAccessibleWrap::RemoveChild(LocalAccessible
* aChild
) {
139 int32_t index
= aChild
->IndexInParent();
141 AtkObject
* atkAccessible
= AccessibleWrap::GetAtkObject(aChild
);
142 atk_object_set_parent(atkAccessible
, nullptr);
143 g_signal_emit_by_name(mAtkObject
, "children_changed::remove", index
,
144 atkAccessible
, nullptr);
146 return ApplicationAccessible::RemoveChild(aChild
);